反映程序集会导致Unity需要Microsoft.Practices.ServiceLocation

Tru*_*ill 5 c# reflection unity-container c#-4.0

我们通常只在我们的应用程序中引用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 {}
Run Code Online (Sandbox Code Playgroud)

在我的机器上,输出是:

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();
Run Code Online (Sandbox Code Playgroud)

再次运行它,它的工作原理.

这是生产代码的简化版本.生产代码实际上是动态加载实现接口的自定义类型.一旦我们介绍了Unity,代码就抛出了异常.但Unity类型无法实现我们的界面!

我不明白如何简单地反映组件导致核心Unity程序集需要另一个依赖项.

Jef*_*eff 7

Unity程序集中的类型,来自Microsoft.Practices.ServiceLocation(可能是IServiceLocator)中定义的接口.

编译器不要求您的应用程序直接引用该DLL ...但反映在System.Type对象上将尝试加载Unity引用的DLL.

这种情况仅在您反映程序集时发生的原因是因为Unity在正常情况下可能不会加载引用Microsoft.Practices.ServiceLocation的类型.

作为解决方法,您可以在try/catch块中包含Assembly.GetTypes()调用.

或者,如果将Microsoft.Practices.ServiceLocation dll放在应用程序可以找到它的位置,那么也应该解决该问题.

  • 完全正确.Unity提供了IServiceLocator的实现.如果不使用它,则不需要服务定位器程序集,但是当您执行反射时,它会引入依赖项以获取接口的元数据. (3认同)