反映在程序集上导致Unity需要Microsoft.Practices.ServiceLocation [英] Reflecting over assemblies causes Unity to require Microsoft.Practices.ServiceLocation

查看:1896
本文介绍了反映在程序集上导致Unity需要Microsoft.Practices.ServiceLocation的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们通常只在我们的应用程序中引用Microsoft.Practices.Unity.dll。我们只使用基本功能,这工作正常。在一个应用程序中,使用反射的行为导致Unity需要另一个DLL。



例如,创建控制台应用程序并仅引用Microsoft.Practices.Unity 2.0.414.0)。输入以下代码并运行:

 类程序
{
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
{
//获取所有加载的程序集,包括Unity。
//获取所有类型。
//过滤可以从中分配ISchemaLoader(自定义类型)的类型。

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(ex.LoaderExceptions中的异常exSub)
{
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 = neutral,PublicKeyToken = 31bf3856ad364e35'或其一个依赖项。系统找不到指定的档案。



现在注释掉

 code> LoadSchemaLoaders(); 

再次运行并运行。



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



我不明白在程序集上简单的反射会导致核心Unity程序集需要另一个依赖。

解决方案

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



编译器不需要您的应用程序直接引用dll ...但是通过System.Type对象反射会尝试加载Unity引用的dll。 / p>

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



作为一种解决方法,您可以在try / catch块中加入Assembly.GetTypes()调用。



,如果你把Microsoft.Practices.ServiceLocation dll在你的应用程序可以找到它的位置,这也应该解决问题。


We typically only reference Microsoft.Practices.Unity.dll in our applications. We're only using basic capabilities, and this works fine. In one application, the act of using reflection is causing Unity to require another DLL.

For example, create a console app and reference only Microsoft.Practices.Unity (file version 2.0.414.0). Enter the following code and run it:

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 {}

On my machine, the output is:

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.

Now comment out the line

LoadSchemaLoaders();

Run it again and it works.

This is a simplified version of production code. The production code is actually dynamically loading custom types that implement an interface. As soon as we introduced Unity, the code threw an exception. But Unity types can't implement our interface!

I don't understand how simply reflecting over the assembly is causing the core Unity assembly to require another dependency.

解决方案

A type in the Unity assembly from an interface defined in Microsoft.Practices.ServiceLocation (probably IServiceLocator).

The compiler doesn't require your application to reference that dll directly...but reflecting over the System.Type object will try to load the dll referenced by Unity.

The reason this only happens when you reflect over the assembly is because Unity probably doesn't load the type that references Microsoft.Practices.ServiceLocation under normal circumstances.

As a work-around, you could enclose your Assembly.GetTypes() call in a try/catch block.

Alternatively, if you put the Microsoft.Practices.ServiceLocation dll in a location where your application can find it, that should resolve the issue as well.

这篇关于反映在程序集上导致Unity需要Microsoft.Practices.ServiceLocation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆