从Path加载程序集

时间:2014-05-26 13:51:35

标签: c# gac

我需要从某个位置加载程序集,而不是从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中,我还能从指定位置加载它?

3 个答案:

答案 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。