从不在GAC中的其他位置加载程序集

时间:2022-11-15 01:51:30

I have several applications which are required to use the same assembly. This assembly may be changed regularly, and can be installed by different MSIs. For this reason, I do not want to put it in the GAC, it can become a deployment nightmare over time.

我有几个应用程序需要使用相同的程序集。该组件可以定期更换,并且可以由不同的MSI安装。出于这个原因,我不想把它放在GAC中,随着时间的推移它可能成为部署的噩梦。

If I turn the CopyLocal attribute for this assembly to NO in the application, how do I tell the runtime where to look for the assembly?

如果我在应用程序中将此程序集的CopyLocal属性设置为NO,如何告诉运行时在哪里查找程序集?

E.g. the application is loaded in C:/Program Files/<some directory>/bin The DLL is in C:/<some other directory>

例如。应用程序加载到C:/ Program Files / / bin DLL位于C:/ <其他目录>

Is it thus possible to load the assembly in this way?

因此可以以这种方式装载组件吗?

I've had a look at <codebase>, but I'm not sure the assembly can be strongly signed. And probing seems to work only for the private paths specified as subdirectories of the application?

我已经看了 ,但我不确定程序集是否可以强烈签名。探测似乎只适用于指定为应用程序子目录的私有路径?

Please let me know. Thank you.

请告诉我。谢谢。

2 个解决方案

#1


1  

Use Assembly.LoadFrom to load the assembly into memory, then you can use Activator.CreateInstance to create an instance of your preferred type. You need to user reflection for this:

使用Assembly.LoadFrom将程序集加载到内存中,然后可以使用Activator.CreateInstance创建首选类型的实例。你需要用户反射:

Assembly assembly = Assembly.LoadFrom("c:\\path\\MyDll.dll");

Type type = assembly.GetType("MyClass");

object instanceOfMyType = Activator.CreateInstance(type);

Take a look on reflection in order to create instances with parameters.

看看反射,以创建带参数的实例。

#2


2  

Why do you want to set CopyLocal to "No"? The usual way to avoid "DLL hell" (aka "deployment nightmare") is to ensure that DLL dependencies are copied into the same directory with your program. IMHO, this is the simplest, most straightforward way to guarantee you are loading the DLL you want.

为什么要将CopyLocal设置为“否”?避免“DLL地狱”(又名“部署噩梦”)的常用方法是确保将DLL依赖项复制到程序的同一目录中。恕我直言,这是保证您加载所需DLL的最简单,最直接的方法。

Note also that if you sign the DLL, install it in the GAC, and then in your own program require a specific version (or a minimum version, depending on your needs), that should also address the "DLL hell" scenarios. I.e. the presence of other versions of the DLL won't conflict, because you've required a specific version and .NET can reliably distinguish the correct version from an incorrect one.

另请注意,如果您对DLL进行签名,请将其安装在GAC中,然后在您自己的程序中需要特定版本(或最低版本,具体取决于您的需要),这也应该解决“DLL地狱”场景。即DLL的其他版本的存在不会发生冲突,因为您需要特定版本,.NET可以可靠地区分正确的版本和不正确的版本。

Barring those approaches...

除非这些方法......

It's not clear what your exact requirements are. However, if you are trying to provide a way to identify an assembly that's not in the usual assembly-loading paths, there are at least a couple of mechanisms you can use.

目前尚不清楚您的具体要求是什么。但是,如果您尝试提供一种方法来识别不在通常的程序集加载路径中的程序集,则至少可以使用几种机制。

One way is to use ApplicationBase and PrivateBinPath to control how .NET searches for your assemblies.

一种方法是使用ApplicationBase和PrivateBinPath来控制.NET搜索程序集的方式。

Another way is to handle the System.AppDomain.AssemblyResolve event.

另一种方法是处理System.AppDomain.AssemblyResolve事件。

That event will be raised any time .NET tries to load a referenced assembly and can't find it. Your handler can then perform whatever search it needs to (or just use a fixed path for that matter), load the assembly itself (e.g. using Assembly.LoadFrom()), and then return that via the event's arguments object.

只要.NET尝试加载引用的程序集而无法找到它,就会引发该事件。然后,您的处理程序可以执行它需要的任何搜索(或者仅使用固定路径),加载程序集本身(例如使用Assembly.LoadFrom()),然后通过事件的arguments对象返回它。

Note that the AssemblyResolve event is only raised if .NET can't find a DLL to load. So that would not be an appropriate solution if it's not tolerable to have a different instance of the DLL that satisfies the reference requirements for the program of that DLL.

请注意,仅当.NET无法找到要加载的DLL时,才会引发AssemblyResolve事件。因此,如果不能容忍DLL的不同实例满足该DLL程序的参考要求,那么这将不是一个合适的解决方案。

#1


1  

Use Assembly.LoadFrom to load the assembly into memory, then you can use Activator.CreateInstance to create an instance of your preferred type. You need to user reflection for this:

使用Assembly.LoadFrom将程序集加载到内存中,然后可以使用Activator.CreateInstance创建首选类型的实例。你需要用户反射:

Assembly assembly = Assembly.LoadFrom("c:\\path\\MyDll.dll");

Type type = assembly.GetType("MyClass");

object instanceOfMyType = Activator.CreateInstance(type);

Take a look on reflection in order to create instances with parameters.

看看反射,以创建带参数的实例。

#2


2  

Why do you want to set CopyLocal to "No"? The usual way to avoid "DLL hell" (aka "deployment nightmare") is to ensure that DLL dependencies are copied into the same directory with your program. IMHO, this is the simplest, most straightforward way to guarantee you are loading the DLL you want.

为什么要将CopyLocal设置为“否”?避免“DLL地狱”(又名“部署噩梦”)的常用方法是确保将DLL依赖项复制到程序的同一目录中。恕我直言,这是保证您加载所需DLL的最简单,最直接的方法。

Note also that if you sign the DLL, install it in the GAC, and then in your own program require a specific version (or a minimum version, depending on your needs), that should also address the "DLL hell" scenarios. I.e. the presence of other versions of the DLL won't conflict, because you've required a specific version and .NET can reliably distinguish the correct version from an incorrect one.

另请注意,如果您对DLL进行签名,请将其安装在GAC中,然后在您自己的程序中需要特定版本(或最低版本,具体取决于您的需要),这也应该解决“DLL地狱”场景。即DLL的其他版本的存在不会发生冲突,因为您需要特定版本,.NET可以可靠地区分正确的版本和不正确的版本。

Barring those approaches...

除非这些方法......

It's not clear what your exact requirements are. However, if you are trying to provide a way to identify an assembly that's not in the usual assembly-loading paths, there are at least a couple of mechanisms you can use.

目前尚不清楚您的具体要求是什么。但是,如果您尝试提供一种方法来识别不在通常的程序集加载路径中的程序集,则至少可以使用几种机制。

One way is to use ApplicationBase and PrivateBinPath to control how .NET searches for your assemblies.

一种方法是使用ApplicationBase和PrivateBinPath来控制.NET搜索程序集的方式。

Another way is to handle the System.AppDomain.AssemblyResolve event.

另一种方法是处理System.AppDomain.AssemblyResolve事件。

That event will be raised any time .NET tries to load a referenced assembly and can't find it. Your handler can then perform whatever search it needs to (or just use a fixed path for that matter), load the assembly itself (e.g. using Assembly.LoadFrom()), and then return that via the event's arguments object.

只要.NET尝试加载引用的程序集而无法找到它,就会引发该事件。然后,您的处理程序可以执行它需要的任何搜索(或者仅使用固定路径),加载程序集本身(例如使用Assembly.LoadFrom()),然后通过事件的arguments对象返回它。

Note that the AssemblyResolve event is only raised if .NET can't find a DLL to load. So that would not be an appropriate solution if it's not tolerable to have a different instance of the DLL that satisfies the reference requirements for the program of that DLL.

请注意,仅当.NET无法找到要加载的DLL时,才会引发AssemblyResolve事件。因此,如果不能容忍DLL的不同实例满足该DLL程序的参考要求,那么这将不是一个合适的解决方案。