加载了 Assembly.LoadFrom 的两个 Dll 定义相同的 Class 并且工作正常?
Two Dlls Loaded with Assembly.LoadFrom Define the Same Class and Work Fine?
这把我吓坏了,我猜这是因为我严重误解了有关如何加载程序集的一些基本知识。我没想到这会起作用,有人可以解释为什么会这样吗?
项目:
- Plugins有一个插件的定义class
- Lib1 引用插件并定义一个插件class
- Lib2 引用插件并定义一个插件class
- 控制台引用插件并查找自身附近的 dll 以加载
Lib1 和 Lib2 通过符号链接共享一个代码文件:
namespace Shared
{
public class SharedClass
{
public static string Key { get; set; }
}
}
Lib1 插件:
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);
}
}
}
Lib2 插件:
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);
}
}
}
}
}
输出:
Lib1 Key
Lib2 Key
Lib1 Key
Lib2 Key
Shared.SharedClass
Shared.SharedClass
它怎么知道区别的!?
您分享的不是编译后的代码,而是SharedClass.cs文件。所以库不知道彼此的 SharedClass,因此没有什么应该 "know the difference"。在编译时,每个插件都链接到包含在同一个程序集中的 SharedClass,而在运行时,有两个 SharedClass,彼此之间一无所知。
没有什么可以阻止两个程序集声明具有相同完全限定名称的类型。这些类型是相似的还是完全不同的(或者在这里,实际上是在同一个源文件中定义的)是无关紧要的。
虽然讨论 extern alias
的页面使用 "two versions of the same assembly" 作为激励示例,但它描述了允许任何消费应用程序消费两个(或更多)声明类型完全相同的库的一般机制-限定类型名称。
You might have to reference two versions of assemblies that have the same fully-qualified type names. For example, you might have to use two or more versions of an assembly in the same application. By using an external assembly alias, the namespaces from each assembly can be wrapped inside root-level namespaces named by the alias, which enables them to be used in the same file.
此外,这归结为完全限定类型名称本身并不能唯一标识特定类型。类型的标识 不仅包括 其名称,还包括其程序集。
这把我吓坏了,我猜这是因为我严重误解了有关如何加载程序集的一些基本知识。我没想到这会起作用,有人可以解释为什么会这样吗?
项目:
- Plugins有一个插件的定义class
- Lib1 引用插件并定义一个插件class
- Lib2 引用插件并定义一个插件class
- 控制台引用插件并查找自身附近的 dll 以加载
Lib1 和 Lib2 通过符号链接共享一个代码文件:
namespace Shared
{
public class SharedClass
{
public static string Key { get; set; }
}
}
Lib1 插件:
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);
}
}
}
Lib2 插件:
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);
}
}
}
}
}
输出:
Lib1 Key
Lib2 Key
Lib1 Key
Lib2 Key
Shared.SharedClass
Shared.SharedClass
它怎么知道区别的!?
您分享的不是编译后的代码,而是SharedClass.cs文件。所以库不知道彼此的 SharedClass,因此没有什么应该 "know the difference"。在编译时,每个插件都链接到包含在同一个程序集中的 SharedClass,而在运行时,有两个 SharedClass,彼此之间一无所知。
没有什么可以阻止两个程序集声明具有相同完全限定名称的类型。这些类型是相似的还是完全不同的(或者在这里,实际上是在同一个源文件中定义的)是无关紧要的。
虽然讨论 extern alias
的页面使用 "two versions of the same assembly" 作为激励示例,但它描述了允许任何消费应用程序消费两个(或更多)声明类型完全相同的库的一般机制-限定类型名称。
You might have to reference two versions of assemblies that have the same fully-qualified type names. For example, you might have to use two or more versions of an assembly in the same application. By using an external assembly alias, the namespaces from each assembly can be wrapped inside root-level namespaces named by the alias, which enables them to be used in the same file.
此外,这归结为完全限定类型名称本身并不能唯一标识特定类型。类型的标识 不仅包括 其名称,还包括其程序集。