从Path加载程序集
我需要从某个位置而不是从GAC加载程序集。 我无法从GAC中删除程序集,因为我的程序必须在不同的计算机上运行,我无法控制程序集是否在GAC中。
我在我的项目中添加了对DLL-File的引用。 不幸的是,汇编是从GAC加载的。
我在Startup
-Event中的App.xaml.cs
中尝试了以下代码
var directory = Thread.GetDomain().BaseDirectory; var dllPath = Path.Combine(directory, "MyAssembly.dll"); var assembly = Assembly.LoadFrom(dllPath);
不幸的是,程序集仍然是从GAC加载的。
即使程序集在GAC中,我还能从指定位置加载它?
不幸的是,您将无法绕过GAC – Assembly.LoadFrom()
, Assembly.LoadFile()
,甚至将其加载到字节数组中并使用Assembly.Load(byte[])
将首先检查GAC具有相同标识的程序集,然后加载它。
您曾经能够在.net 1.1中执行您想要的操作,但从2.0开始,首先检查GAC。 请参阅运行时如何查找程序集 – 请注意,第3步是在探测目录之前检查GAC(即使您已完全指定它)
如果要为Reflection加载一个(检查程序集,而不是运行它),可以使用Assembly.ReflectionOnlyLoadFrom()
查看MSDN上的Assembly.LoadFrom()
。
来自MSDN:
Assembly SampleAssembly; SampleAssembly = Assembly.LoadFrom("c:\\Sample.Assembly.dll"); // Obtain a reference to a method known to exist in assembly. MethodInfo Method = SampleAssembly.GetTypes()[0].GetMethod("Method1"); // Obtain a reference to the parameters collection of the MethodInfo instance. ParameterInfo[] Params = Method.GetParameters(); // Display information about method parameters. // Param = sParam1 // Type = System.String // Position = 0 // Optional=False foreach (ParameterInfo Param in Params) { Console.WriteLine("Param=" + Param.Name.ToString()); Console.WriteLine(" Type=" + Param.ParameterType.ToString()); Console.WriteLine(" Position=" + Param.Position.ToString()); Console.WriteLine(" Optional=" + Param.IsOptional.ToString()); }
即使在加载自定义程序集之后,也不能像通常那样简单地调用方法或使用类型。 看看这个从这个问题中偷来的例子,它应该指向正确的方向:
Assembly assembly = Assembly.LoadFile("myAssembly"); Type type = assembly.GetType("myAssembly.ClassName"); if (type != null) { MethodInfo methodInfo = type.GetMethod("MyMethod"); if (methodInfo != null) { object result = null; ParameterInfo[] parameters = methodInfo.GetParameters(); object classInstance = Activator.CreateInstance(type, null); if (parameters.Length == 0) { //This works fine result = methodInfo.Invoke(classInstance, null); } else { object[] parametersArray = new object[] { "Hello" }; //The invoke does NOT work it throws "Object does not match target type" result = methodInfo.Invoke(classInstance, parametersArray); } } }
看一下ILMerge ( 使用ILMerge合并.NET程序集的文章)
它应该允许您将DLL与您的代码合并,因此不会下载外部任何内容,也不会支付reflection成本,因此性能应该更好。
ILMerge获取一组输入程序集并将它们合并到一个目标程序集中。 输入程序集列表中的第一个程序集是主程序集。 当主程序集是可执行文件时,目标程序集将创建为具有与主程序集相同的入口点的可执行文件。 此外,如果主程序集具有强名称,并且提供了.snk文件,则使用指定的键重新签名目标程序集,以使其具有强名称。
另一个选择是从该DLL中删除强名称。 在这里看看C#中的assembly操作
Reflexil能够删除程序集强名称和更新引用程序集。 您也可以使用汇编编辑器自行完成:删除公钥并将HasPublicKey标志设置为false。