Отразяването върху сглобките кара Unity да изисква Microsoft.Practices.ServiceLocation

Обикновено се позоваваме само на Microsoft.Practices.Unity.dll в нашите приложения. Използваме само основни възможности и това работи добре. В едно приложение актът на използване на отражение кара Unity да изисква друг DLL.

Например, създайте конзолно приложение и препратете само към Microsoft.Practices.Unity (версия на файла 2.0.414.0). Въведете следния код и го стартирайте:

class Program
{
    static void Main()
    {
        using (var container = new UnityContainer())
        {
            container.RegisterType<IDoSomething, ConcreteDoSomething>();

            var thing = container.Resolve<IDoSomething>();

            thing.DoSomething();
            Console.WriteLine();

            LoadSchemaLoaders();
        }
    }

    public static void LoadSchemaLoaders()
    {
        var type = typeof(ISchemaLoader);

        try
        {
            // Get all loaded assemblies, including Unity.
            // Get all of the types.
            // Filter for types that ISchemaLoader (custom type) can be assigned from.

            var types = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(s => s.GetTypes())
                .Where(c => type.IsAssignableFrom(c) && c.IsClass && !c.IsAbstract && !c.IsGenericParameter);

            Console.WriteLine("Got here...");

            types.FirstOrDefault();
        }
        catch (ReflectionTypeLoadException ex)
        {
            Console.WriteLine(ex.Message);

            foreach (Exception exSub in ex.LoaderExceptions)
            {
                Console.WriteLine(exSub.Message);
            }
        }
    }
}

public interface IDoSomething
{
    void DoSomething();
}

public class ConcreteDoSomething : IDoSomething
{
    public void DoSomething()
    {
        Console.WriteLine("Something!");
    }
}

public interface ISchemaLoader {}

На моята машина изходът е:

Something!

Got here...
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Could not load file or assembly 'Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.

Сега коментирайте реда

LoadSchemaLoaders();

Стартирайте го отново и работи.

Това е опростена версия на производствен код. Производственият код всъщност динамично зарежда персонализирани типове, които имплементират интерфейс. Веднага след като представихме Unity, кодът хвърли изключение. Но типовете Unity не могат да имплементират нашия интерфейс!

Не разбирам как простото отразяване върху сглобката кара основната сглобка на Unity да изисква друга зависимост.


person TrueWill    schedule 06.04.2012    source източник


Отговори (1)


Тип в сборката на Unity от интерфейс, дефиниран в Microsoft.Practices.ServiceLocation (вероятно IServiceLocator).

Компилаторът не изисква вашето приложение да препраща директно към този dll... но отразяването върху обекта System.Type ще се опита да зареди dll, посочен от Unity.

Причината, поради която това се случва само когато размишлявате над сборката, е, че Unity вероятно не зарежда типа, който препраща към Microsoft.Practices.ServiceLocation при нормални обстоятелства.

Като заобиколно решение можете да затворите извикването на Assembly.GetTypes() в блок try/catch.

Като алтернатива, ако поставите Microsoft.Practices.ServiceLocation dll на място, където вашето приложение може да го намери, това също трябва да разреши проблема.

person Jeff    schedule 06.04.2012
comment
Точно така. Unity предоставя имплементация на IServiceLocator. Ако не го използвате, нямате нужда от модула за локатор на услуги, но когато направите отражението, той изтегля зависимостта, за да получи метаданните на интерфейса. - person Chris Tavares; 07.04.2012
comment
Благодаря! Филтрирането на сглобките с .Where(x => x.FullName.StartsWith("OurCompanyName.")) го поправи. Добре е да знам защо се случваше. - person TrueWill; 09.04.2012
comment
Иска ми се да можех да гласувам за това отново - след като ми спаси бекона... отново. Не е най-елегантното решение.. но е достатъчно елегантно. - person Jon H; 08.03.2018