对程序集进行反射会导致 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 {}

在我的机器上,输出是:

东西!到了这里...无法加载一个或多个请求的类型。检索 LoaderExceptions 属性以获取更多信息。无法加载文件或程序集"Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=中性, PublicKeyToken=31bf3856ad364e35' 或其依赖项之一。系统找不到指定的文件。

现在注释掉该行

LoadSchemaLoaders();

再次运行它,它可以工作。

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

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

Unity

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

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

之所以仅在对程序集进行反射时才发生这种情况,是因为 Unity 在正常情况下可能不会加载引用 Microsoft.Practices.ServiceLocation 的类型。

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

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