【问题标题】:Create object from dynamically load assembly and cast it to interface (.NET 2.0)从动态加载程序集创建对象并将其转换为接口(.NET 2.0)
【发布时间】:2011-11-08 23:36:55
【问题描述】:

我在动态加载程序集并将其转换为接口时遇到问题。我的错误在哪里?

主应用(加载插件):

namespace Console_IFce_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Press any key to find IPlugin library...");
            Console.ReadKey();            

            string[] files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll");
            Console.WriteLine("Loading assembly: {0}", Path.GetFileName(files[0]));

            Assembly asm = Assembly.LoadFrom(files[0]);
            //Trying this, but still have problems
            //Assembly asm = Assembly.Load(File.ReadAllBytes(files[0])); 

            foreach (Type t in asm.GetTypes())
            {
                Console.WriteLine("Searching in type {0}... ", t.FullName);

                foreach (Type iface in t.GetInterfaces())
                {
                    Console.WriteLine("Interface found: {0}", iface.FullName);
                }

                if (t is IPlugin)
                {
                    Console.WriteLine("1 - IPlugin found!");
                    IPlugin plugin = (IPlugin)Activator.CreateInstance(t);
                    return;
                }

                if (typeof(IPlugin).IsAssignableFrom(t))
                {
                    Console.WriteLine("2 - IPlugin found!");
                    IPlugin plugin = (IPlugin)Activator.CreateInstance(t);
                    return;
                }
            }

            Console.WriteLine("All operations done! Press any key to exit...");
            Console.ReadKey();
        }
    }
}

界面:

namespace Console_IFce_Test
{
    interface IPlugin
    {
        int GetZero();
    }
}

还有插件:

namespace Library
{
    public class Plugin : Console_IFce_Test.IPlugin
    {
        public int GetZero()
        {
            return 0;
        }
    }
}

在带有 .exe 的目录中 - 只有 1 个 .dll(插件)。所以,它的输出:

Press any key to find IPlugin library... 
Loading assembly: Library.dll 
Searching in type Console_IFce_Test.IPlugin... 
Searching in type Library.Plugin... 
Interface found: Console_IFce_Test.IPlugin 
All operations done! Press any key to exit...

您看,该程序在程序集中找到了 IPlugin 接口,但是当我尝试将它与接口(两个条件语句)进行比较时 - 它们返回 false。如果我尝试手动投射它 - 它会返回异常“无法投射”。

我发现了类似的问题:Two Types not equal that should be,答案作者:

不同应用程序域 [.NET] 或类加载的相同类/类型 loaders [Java] 不会比较相等,也不能分配给/从 直接互怼。

但我不明白我该怎么办?怎么做?

【问题讨论】:

  • 避免此陷阱的最佳方法是使用接口类型创建第三个程序集。主机和插件都引用。这可确保您不会在多个程序集中使用相同的类型。
  • 我试试。没有结果。我感觉,我犯了一个非常愚蠢的错误,但我无法理解 - 在哪里?

标签: c# .net interface dynamic


【解决方案1】:

您需要以某种方式使 .NET 将程序集加载到相同的上下文中,以便能够在这些程序集中的类型之间进行强制转换。

1- 将程序集放在应用程序路径或 GAC 中,以便 Load(而不是 LoadFrom)函数可以找到它。

2- 创建一个应用程序域并在那里完成所有工作。您可以完全控制在哪里搜索应用程序域的程序集。

3- 使用插件模型。

阅读本文以了解有关您的选择的更多信息:Best Practices for Assembly Loading

【讨论】:

    【解决方案2】:

    在 .Net 中,类型通过上下文和名称来区分...

    LoadFrom 在不同于正常加载到程序中的任何类型的上下文中加载类型

    因此,您有两种不同类型的 IPlugin,一种在默认上下文中加载,另一种在 LoadFrom 上下文中。它们不会进行相同的比较,并且您不能在它们之间进行转换。

    如果您希望它们与在默认上下文中加载的类型相同,则必须确保通过 LoadFrom 加载的程序集引用的类型无法在 LoadFrom 上下文中解析。

    【讨论】:

    • 谢谢。但是您有什么想法,我该如何解决这个问题?我正在尝试使用 Assembly.Load(byte[]) 方法,将 .dll 读取到内存中,但它也不起作用。
    猜你喜欢
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多