使用AssemblyResolve处理C#中缺少的程序集 [英] Using assemblyresolve to handle missing assemblies in C#

查看:369
本文介绍了使用AssemblyResolve处理C#中缺少的程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 http://support.microsoft.com/kb/837908在C#中动态加载程序集.但是,该代码对我不起作用.在代码的以下部分中,仅当缺少的程序集的名称是应用程序引用的程序集之一时,作者才加载缺少的程序集.

I am following Method 3 in http://support.microsoft.com/kb/837908 to load assemblies dynamically in C#. However, the code is not working for me. In the following section of the code, the author loads the missing assembly only if the name of missing assembly is one of the assemblies referenced by the application.

在调试下运行该函数时,将调用该函数,但是缺少的程序集不在这些引用的程序集中,因此在我的情况下未设置该程序集.任何想法为什么会这样?我不确定该DLL是C#还是本机C ++.难道是因为无法以这种方式加载C ++ dll吗?那么,为什么要为缺少的C ++程序集调用此函数呢?任何解释表示赞赏.如果此方法不适用于从C#引用的C ++程序集,那么有什么替代方法?

When I run this under debug, the function is getting called, but the missing assembly is not in any of those referenced assemblies, and so it is not set in my case. Any ideas why is this occurring? I am not sure if that DLL is C# or native C++. Could this be because C++ dlls cannot be loaded this way? Then, why is this function getting invoked for a missing C++ assembly? Any explanations appreciated. If this doesn't work for C++ assemblies referenced from C#, what are alternatives?

private Assembly MyResolveEventHandler(object sender,ResolveEventArgs args)
{
    //This handler is called only when the common language runtime tries to bind to the assembly and fails.

    //Retrieve the list of referenced assemblies in an array of AssemblyName.
    Assembly MyAssembly,objExecutingAssemblies;
    string strTempAssmbPath="";

    objExecutingAssemblies=Assembly.GetExecutingAssembly();
    AssemblyName [] arrReferencedAssmbNames=objExecutingAssemblies.GetReferencedAssemblies();

    //Loop through the array of referenced assembly names.
    foreach(AssemblyName strAssmbName in arrReferencedAssmbNames)
    {
        //Check for the assembly names that have raised the "AssemblyResolve" event.
        if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(","))==args.Name.Substring(0, args.Name.IndexOf(",")))
        {
            //Build the path of the assembly from where it has to be loaded.                
            strTempAssmbPath="C:\\Myassemblies\\"+args.Name.Substring(0,args.Name.IndexOf(","))+".dll";
            break;
        }

    }
    //Load the assembly from the specified path.                    
    MyAssembly = Assembly.LoadFrom(strTempAssmbPath);                   

    //Return the loaded assembly.
    return MyAssembly;          
}

推荐答案

术语程序集"不仅仅意味着任何DLL;它还指的是任何DLL.这表示使用.NET创建并为.NET创建的DLL.它通常也被称为托管代码",这大致意味着您使用.NET垃圾收集器,而不是使用常规的C ++堆来管理内存. (我正在简化.尽管混合模式程序集"混合使用托管和非托管代码,但确实可以通过这种方式解决.托管"的含义远不只是内存管理.)

The term "assembly" does not mean just any DLL; it means a DLL created with and for .NET. It is also often called "managed code" which roughly means that you use the .NET garbage collector rather than a conventional C++ heap for managing memory. (I am simplifying. There are also "mixed mode assemblies" which do get resolved this way although they use a mix of managed and unmanaged code. And "managed" means quite a bit more than just memory management.)

您引用的程序集是用C ++/CLI还是C#编写都没有关系. C ++/CLI通常与C ++混淆,但实际上它是另一种具有额外功能的语言,可以利用托管环境.如果使用/clr开关编译C ++类的东西,则它是C ++/CLI而不是C ++.

It does not matter whether your referenced assembly is written in C++/CLI, or in C#. C++/CLI is often confused with C++, but it is actually another language with extra facilities to take advantage of the managed environment. If you compile something C++'ish with the /clr switch, it's C++/CLI rather than C++.

您需要了解带有参考知识库文章的三个陷阱.

There are three gotchas with the referenced KB article that you need to understand.

    本文中的
  1. 方法3"没有考虑间接引用的程序集.也就是说,从主装配引用的装配引用的装配.这可能现在在咬你.

  1. "Method 3" in the article does not take indirectly referenced assemblies into account. That is, assemblies referenced from assemblies referenced from your main assembly. This is probably biting you right now.

这篇文章没有提到,至关重要的是,您必须在注册处理程序的方法主体中尽可能少地执行 ,否则抖动将在处理程序之前解析一些程序集已注册-即使负责该操作的代码行低于同一方法中的注册.这是因为JIT编译先于执行.

The article fails to mention that it is critical that you do as little as possible in the body of the method that registers your handler, or the jitter will resolve some assemblies before your handler is registered - even if the code lines responsible for that are below the registration in the same method. This is because JIT compilation precedes execution.

如果要处理C ++/CLI代码,很可能还需要加载前者链接所针对的一些非托管C ++ DLL.它是使用传统的Windows DLL搜索顺序并在解析器外部完成的.但这不是您的问题,只要您看到为特定的DLL输入了处理程序即可.与.NET无关的普通C或C ++ DLL根本不会在处理程序中看到.

If you deal with C++/CLI code, odds are that you also need to load some unmanaged C++ DLLs that the former link against. It is done using the traditional Windows DLL search order and outside of your resolver. But this is not your problem as long as you see the handler entered for a particular DLL. A normal kind of C or C++ DLL that has nothing to do with .NET will not be seen in the handler at all.

这篇关于使用AssemblyResolve处理C#中缺少的程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆