我需要从某个位置加载程序集,而不是从GAC加载。我无法从GAC中删除程序集,因为我的程序必须在不同的计算机上运行,我无法控制程序集是否在GAC中。
我在我的项目中添加了对DLL-File的引用。不幸的是,汇编是从GAC加载的。
我在App.xaml.cs
中的Startup
- 事件
var directory = Thread.GetDomain().BaseDirectory;
var dllPath = Path.Combine(directory, "MyAssembly.dll");
var assembly = Assembly.LoadFrom(dllPath);
不幸的是,程序集仍然是从GAC加载的。
即使程序集在GAC中,我还能从指定位置加载它?
答案 0 :(得分:14)
不幸的是,您将无法绕过GAC - Assembly.LoadFrom()
,Assembly.LoadFile()
,甚至将其加载到字节数组中并使用Assembly.Load(byte[])
将首先检查GAC具有相同标识的程序集,然后加载它。
您使用能够在.net 1.1中执行您想要的操作,但从2.0开始,首先检查GAC。 See How the Runtime Locates Assemblies - 请注意,第3步是在探测目录之前检查GAC(即使您已完全指定它)
如果你想为Reflection加载一个(检查程序集,而不是运行它),你可以使用Assembly.ReflectionOnlyLoadFrom()
答案 1 :(得分:3)
查看Assembly.LoadFrom()
on MSDN.
来自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());
}
即使在加载自定义程序集后,也不能像通常那样简单地调用方法或使用类型。看看这个从this question偷来的例子,它应该指向正确的方向:
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);
}
}
}
答案 2 :(得分:0)
查看ILMerge(文章Merging .NET assemblies using ILMerge)
它应该允许您将DLL与您的代码合并,因此不会下载任何外部内容,并且您不会支付反射成本,因此性能应该更好。
ILMerge获取一组输入程序集并将它们合并为一个 目标装配。输入程序集列表中的第一个程序集是 主要组件。当主程序集是可执行文件时,那么 目标程序集创建为具有相同条目的可执行文件 指向主要组件。此外,如果主要组件有一个 强名称,并提供.snk文件,然后目标程序集 使用指定的密钥重新签名,以便它也具有强名称。
另一种选择是从该DLL中删除强名称。看这里Assembly Manipulation in C#
Reflexil能够删除程序集强名称和更新引用 组件。您也可以使用汇编编辑器自己完成: 删除公钥并将HasPublicKey标志设置为false。