用Assembly.LoadFrom加载的两个Dll定义相同的类并且工作正常?

时间:2017-01-10 19:42:05

标签: c# dll assemblies dllimport

这让我感到非常震惊,我猜测它是因为我严重误解了关于程序集如何加载的基本信息。我没想到这会起作用,有人可以解释它为什么会这样吗?

项目:

  • 插件具有插件类的定义
  • Lib1引用插件并定义插件类
  • Lib2引用插件并定义了一个插件类
  • 控制台引用插件并查找附近的dll以加载

Lib1和Lib2通过符号链接共享代码文件:

User_UserID

Lib1插件:

namespace Shared
{
    public class SharedClass
    {
        public static string Key { get; set; }
    }
}

Lib2插件:

namespace Lib1
{
    public class Lib1Plugin : Plugin
    {
        public override void Load()
        {
            SharedClass.Key = "Lib1 Key";

            Console.WriteLine(SharedClass.Key);
        }

        public override void Run()
        {
            Console.WriteLine(SharedClass.Key);
        }
    }
}

控制台:

namespace Lib2
{
    public class Lib2Plugin : Plugin
    {
        public override void Load()
        {
            SharedClass.Key = "Lib2 Key";

            Console.WriteLine(SharedClass.Key);
        }

        public override void Run()
        {
            Console.WriteLine(SharedClass.Key);
        }
    }
}

输出:

    static class Functions
    {
        public static IEnumerable<Type> FindDerivied(Assembly asm, Type baseType)
        {
            try
            {
                return asm.GetTypes().Where(t => baseType.IsAssignableFrom(t) && t != baseType);
            }
            catch (Exception e)
            {
                return new List<Type>();
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var di = new DirectoryInfo("Plugins");

            var bos = new List<Plugin>();
            if (di.Exists)
            {
                var dlls = di.EnumerateFiles();
                foreach (var dll in dlls)
                {
                    var asm = Assembly.LoadFrom(dll.FullName);

                    var builders = Functions.FindDerivied(asm, typeof(Plugin));
                    foreach (var builder in builders)
                    {
                        var bo = (Plugin)Activator.CreateInstance(builder);

                        bo.Load();
                        bos.Add(bo);
                    }
                }

                foreach (var bo in bos)
                {
                    bo.Run();
                }

                var asms = AppDomain.CurrentDomain.GetAssemblies();
                foreach (var asm in asms)
                {
                    var exports =
                        asm.GetExportedTypes().Where(type => type.Name == "SharedClass")
                        .ToList();

                    foreach (var export in exports)
                    {
                        Console.WriteLine(export.FullName);
                    }
                }
            }
        }
    }

它是如何知道差异的??

2 个答案:

答案 0 :(得分:2)

没有什么可以阻止两个程序集声明具有相同完全限定名称的类型。这些类型是相似还是完全不同(或者在这里,实际上是在同一个源文件中定义)是无关紧要的。

虽然讨论extern alias的页面使用&#34;同一个程序集的两个版本&#34;作为它的激励示例,它描述了允许任何消费应用程序使用两个(或更多)库来声明具有相同完全限定类型名称的类型的一般机制。

  

您可能必须引用具有相同完全限定类型名称的两个版本的程序集。例如,您可能必须在同一应用程序中使用两个或更多版本的程序集。通过使用外部程序集别名,每个程序集的名称空间可以包装在别名命名的根级名称空间中,这使它们可以在同一文件中使用。

此外,这归结为完全限定的类型名称本身并不唯一地标识特定类型。类型的标识不仅包括名称,还包括其程序集。

答案 1 :(得分:0)

您没有共享已编译的代码,而是共享文件SharedClass.cs文件。因此,图书馆不了解彼此的SharedClass,因此没有什么应该知道差异&#34;。在编译时,每个插件都链接到同一个程序集中包含的SharedClass,并且在运行时有两个SharedClasses彼此不知道。