Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#-使用反射从程序集加载时的不同类型_C#_.net_Reflection_.net Assembly - Fatal编程技术网

c#-使用反射从程序集加载时的不同类型

c#-使用反射从程序集加载时的不同类型,c#,.net,reflection,.net-assembly,C#,.net,Reflection,.net Assembly,我有一个包含3个项目的解决方案: 1) GUI可执行文件 2) 具有包含公共API和公共接口的 3) 实现上述接口的类的类库 我试图在API中实现一个资源加载器,这样当GUI调用方法API.Foo()时,我会检查特定文件夹(位于:.\resources)中的每个程序集,其中包含我编译的程序集(#3)的副本。 然后,我想将资源添加到列表中,并使用此列表调用作为接口一部分的函数(每个资源都实现该接口) 所以我所做的是: private List<IResource> m_resource

我有一个包含3个项目的解决方案: 1) GUI可执行文件 2) 具有包含公共API和公共接口的 3) 实现上述接口的类的类库

我试图在API中实现一个资源加载器,这样当GUI调用方法
API.Foo()
时,我会检查特定文件夹(位于:.\resources)中的每个程序集,其中包含我编译的程序集(#3)的副本。 然后,我想将资源添加到列表中,并使用此列表调用作为接口一部分的函数(每个资源都实现该接口)

所以我所做的是:

private List<IResource> m_resources;

public void Foo()
{
    string resourceDir = Directory.GetCurrentDirectory() + @"\Resources";
    m_resources= new List<IResource>();
    foreach (var dllFile in  Directory.EnumerateFiles(resourceDir))
    {
        IResource dllInstance;
        if (TryLoadingDLL(Path.Combine(resourceDir, dllFile), out dllInstance))
        {
            resources.Add(dllInstance);
        }
    }
}

private static bool TryLoadingDLL(string dllFullPath, out  IResource instanceOfDll)
{
    instanceOfDll = null;
    try
    {
        Assembly assembly = Assembly.LoadFrom(dllFullPath);
        Assembly IResourceAssambly = Assembly.LoadFrom(@"C:\MyProject\MyAPI.dll");
        Type[] types = assembly.GetTypes();
        foreach (Type type in types)
        {
            var interfaces = type.GetInterfaces();
            var typeOfIResource = IResourceAssambly.GetType("MyProject.IResource");
            if (interfaces.Any())
            {
                var interfaceType = interfaces[0]; //In debuger they have the same GUID
                if (interfaceType.IsEquivalentTo(typeOfIResource)) //also tried ==
                {
                    instanceOfDll = Activator.CreateInstance(type) as IResource;
                    return true;
                }
            }
        }
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("Failed to load dll {0}, exception: {1}",dllFullPath, e.Message);
        return false;
    }
    return false;
}

问题似乎来自于类型,因此我尝试更换

var typeOfIResource = IResourceAssambly.GetType("MyProject.IResource");

结果是现在它没有找到任何东西,即
interfaceType.IsEquivalentTo(typeOfIResource)
总是false。 当我使用调试器查看这些类型时,它们看起来完全相同,所以我不知道问题出在哪里

首先,这是一种好的做法吗?我希望其他开发人员向我提供他们的程序集,如果他们实现了IResource接口,则使用反射创建实例并调用所需的方法

第二个也是更重要的一个问题是什么?我该如何解决


谢谢

Look system.component,自.NET 4以来,框架MEF已被集成


此框架允许您在接口的每个实现上使用属性[Export(typeof(interface))]标记,而不考虑dll,并使用目录系统加载它们。(文件夹有一个,这让我想起了过去;我在写的第一个.NET程序中遇到了同样的问题,那一定是15年前的事了

问题是.NET具有不同的“绑定上下文”,其中可以加载类型,“加载”和“加载自”加载到不同的上下文中。运行时会将两个不同上下文中的“相同”类型视为不同的类型,并且不能在它们之间强制转换

这是关于堆栈溢出的一个相当常见的问题;如果您搜索这些术语,您应该会找到一些解释和可能的解决方案的示例。例如,以下示例:

此外,这篇来自.NET早期的博客文章可能有助于解释设计


最后,另一个答案是正确的;如果你想构建一个插件系统,我建议不要从头开始。使用MEF或MAF或其他专门为解决你的问题而设计的系统。加载程序集可能是你最不担心的事情;假设你一定生活在一个第三方插件可能敌对的世界里?解决这个安全问题很难解决,所以让其他人来帮你解决。

有什么特别的原因你不只是为了这个而使用
MEF
吗?我不熟悉MEF。我们想要这个设计的原因是可伸缩性。将来添加的程序集将是我们自己的,它们代表了计算同一事物的不同方式,例如在所有的方法都返回了一个答案之后,我们以某种方式混合了结果。好吧,这里有一个愚蠢的问题。它们是否真的引用了相同的接口(在一些常见的程序集中)或者他们只是有一份文件的副本吗?我会更容易地调查MEF。我会调查的,谢谢。他们都在同一个解决方案下,从解决方案内部引用,但我认为他们使用的是本地副本:/很快就会更新。这很尴尬……我确实在:|@BradleyDotNet上有副本本地标志,谢谢你的支持umb问题:P
{System.InvalidCastException: Unable to cast object of type 'MyProject.MyFirstResource' to type 'MyProject.IResource'.
var typeOfIResource = IResourceAssambly.GetType("MyProject.IResource");
var typeOfIResource = typeof(MyProject.IResource);