AppDomain.CurrentDomain.AssemblyResolve在Dynamics CRM中 [英] AppDomain.CurrentDomain.AssemblyResolve in dynamics crm

查看:581
本文介绍了AppDomain.CurrentDomain.AssemblyResolve在Dynamics CRM中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我得的多篇文章引用使用 AppDomain.CurrentDomain.AssemblyResolve 从嵌入的资源DLL文件加载到在运行时插件(不使用IlMerge)。然而,当我插入此代码,事件处理程序永远不会收到该线程的插件会因我的主要图书馆TypeLoadException消息之前。

So, I've come by many articles referencing the use of AppDomain.CurrentDomain.AssemblyResolve to load DLLs from embedded resources into a plugin at runtime (without the use of IlMerge). However, when I insert this code, the event handler never receives the thread before the plugin throws a TypeLoadException message for my main library.

我曾尝试把代码中的一个静态构造函数,在主构造Execute方法,并在里面;虽然事件处理程序被注册,在处理程序中的断点不被打到。

I have tried placing the code in a static constructor, inside of the Execute method and in the main constructor; and although the event handler is registered, breakpoints in the handler do not get hit.

环境是动态CRM 2011年最新的侧倾和使用SDK开发工具插件项目和插件类生成。

The environment is Dynamics CRM 2011 with latest roll up and using the SDK developer tools Plugin project and plugin class generation.

任何人都知道我需要怎样做才能得到这个工作是什么?

Anyone know what I need to be doing to get this to work?

推荐答案

据您从您通过该回调计划装载组件引用任何类型的前AssemblyResolve事件发生的注册是非常重要的。即使你不引用类型的静态构造函数,你也必须确保你没有静态变量在类或它的基类在外部程序集的引用类型。

It's important that the AssemblyResolve event registration happen before you reference any types from the assemblies you plan on loading via that callback. Even if you don't reference the types in your static constructor, you have to also ensure you have no static variables in the class or it's base classes that reference types in the external assemblies.

下面是我如何做到这一点:$ b​​ $ b我有一个单独的类来处理总成装车,取名为AssemblyLoader:

Here's how I do it: I have a separate class to handle the assembly loading, aptly named AssemblyLoader:

using System;
using System.IO;
using System.Linq;
using System.Reflection;

internal static class AssemblyLoader
{
    internal static void RegisterAssemblyLoader()
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyResolve -= OnResolveAssembly;
        currentDomain.AssemblyResolve += OnResolveAssembly;
    }

    private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
    {
        return LoadAssemblyFromManifest(args.Name);
    }

    private static Assembly LoadAssemblyFromManifest(string targetAssemblyName)
    {
        Assembly executingAssembly = Assembly.GetExecutingAssembly();
        AssemblyName assemblyName = new AssemblyName(targetAssemblyName);

        string resourceName = DetermineEmbeddedResourceName(assemblyName, executingAssembly);

        using (Stream stream = executingAssembly.GetManifestResourceStream(resourceName))
        {
            if (stream == null)
                return null;

            byte[] assemblyRawBytes = new byte[stream.Length];
            stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);


            return Assembly.Load(assemblyRawBytes);
        }

    }

    private static string DetermineEmbeddedResourceName(AssemblyName assemblyName, Assembly executingAssembly)
    {
        //This assumes you have the assemblies in a folder named "EmbeddedAssemblies"
        string resourceName = string.Format("{0}.EmbeddedAssemblies.{1}.dll",
                                            executingAssembly.GetName().Name, assemblyName.Name);

        //This logic finds the assembly manifest name even if it's not an case match for the requested assembly                          
        var matchingResource = executingAssembly.GetManifestResourceNames()
                                                .FirstOrDefault(res => res.ToLower() == resourceName.ToLower());

        if (matchingResource != null)
        {
            resourceName = matchingResource;
        }
        return resourceName;
    }
}



然后,在我的插件类,我用一个静态的构造函数调用到我AssemblyLoader。通过逻辑移动到单独的类,我限制的类型,我引用在我的插件类的静态背景下,这样可以减少我意外地引用东西是在外部组件的风险数量。

Then, in my plugin class, I use a static constructor to call into my AssemblyLoader. By moving the logic into the separate class, I limit the number of types I'm referencing in my plugin class's static context, thus reducing the risk I accidentally reference something that's in the external assemblies.

using System;
using Microsoft.Xrm.Sdk;

public class MyPlugin : IPlugin
{
    static MyPlugin()
    {
        AssemblyLoader.RegisterAssemblyLoader();
    }

    public void Execute(IServiceProvider serviceProvider)
    {
        //...
    }
}

我也感动几乎所有的外部组件的用法到其他类别,使得我的插件类没有在使用所有。大多数情况下,这是出于谨慎的。

I also moved pretty much all of the usages of the external assemblies into other classes so that my plugin class doesn't use the at all. Mostly, this is out of an abundance of caution.

这篇关于AppDomain.CurrentDomain.AssemblyResolve在Dynamics CRM中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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