在应用程序域中加载静态类 [英] Load static class in appdomain

查看:25
本文介绍了在应用程序域中加载静态类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 C# AppDomain 中遇到了一个大问题.

我需要在 .dll 文件中加载一个静态类并执行它的方法:

  1. 当我尝试加载它们时

    Assembly.LoadFrom("XXXXX")//(XXXXX为dll的完整路径)

    不会自动或以编程方式卸载 .dll.

  2. 当我尝试在 AppDomain 中加载它们时

    adapterDomain = AppDomain.CreateDomain("AdapterDomain");(a)adapterDomain.CreateInstanceFrom(this.AdapterFilePath, this.AdapterFullName);(b)adapterAssembly=adapterDomain.Load(AssemblyName.GetAssemblyName(this.AdapterFilePath));

    如果我使用方法(a),因为目标类是静态类,它不起作用.

    如果我使用方法(b),因为目标.dll和我的项目不在同一个目录,我会得到一个异常.

如何加载.dll和静态类,使用后卸载.dll?

解决方案

方法 (b) 失败,因为 AppDomain.Load 无法解析不在基本应用程序目录、探测专用路径或 GAC 中的程序集.

另请注意,AppDomain.Load 将程序集加载到特定的 AppDomain 上(例如示例代码中的 adapterDomain.Load).相反,它将它加载到当前的 AppDomain(这是调用 AppDomain.Load 的那个.此行为在 MSDN 文档.)显然这不是您要找的.

以下是如何在子 AppDomain 中调用静态方法的示例:

class 程序{静态无效主(字符串 [] args){//这是为了测试目的!var loadedAssembliesBefore = AppDomain.CurrentDomain.GetAssemblies();var domain = AppDomain.CreateDomain("ChildDomain");//这将调用 dhild AppDomain 中的静态方法.domain.DoCallBack(LoadAssemblyAndCallStaticMethod);//在子 AppDomain 上打印加载的程序集.这是为了测试目的!domain.DoCallBack(PrintLoadedAssemblies);AppDomain.Unload(域);//这是为了测试目的!var loadedAssembliesAfter = AppDomain.CurrentDomain.GetAssemblies();//断言没有程序集泄漏到主 AppDomain.Debug.Assert(!loadedAssembliesBefore.Except(loadedAssembliesAfter).Any());Console.ReadKey();}//加载StaticMethodInHere.dll到当前AppDomain并调用静态方法//静态类.DoSomething.静态无效 LoadAssemblyAndCallStaticMethod(){var assembly = Assembly.LoadFrom(@"PATH_TO_ASSEMBLY");assembly.GetType("CLASS_CONTAINING_STATIC_METHOD").InvokeMember("STATIC_METHOD",BindingFlags.Public |BindingFlags.Static |BindingFlags.InvokeMethod,空值,空值,空值);}//打印当前 AppDomain 中加载的组件.用于测试目的.静态无效 PrintLoadedAssemblies(){Console.WriteLine("/程序集在 {0} -------------------------------",AppDomain.CurrentDomain.FriendlyName);foreach(AppDomain.CurrentDomain.GetAssemblies() 中的 var 程序集){Console.WriteLine(assembly.FullName);}}}

要完成这项工作,您需要替换:

  • PATH_TO_ASSEMBLY 包含包含扩展的静态方法的程序集的路径.
  • CLASS_CONTAINING_STATIC_METHOD 包含包含静态方法的类的名称,包括类的命名空间.
  • STATIC_METHOD 带有静态方法的名称.

请注意,BindingFlags 是为公共静态方法设置的.

I'm met with a big problem in C# AppDomain.

I need to load a static class in a .dll file and execute its method:

  1. When I try to load them by

    Assembly.LoadFrom("XXXXX") // (XXXXX is the full path of dll)
    

    the .dll will not be unload automatically or programmatically.

  2. When I try to load them in AppDomain like

    adapterDomain = AppDomain.CreateDomain("AdapterDomain");
    (a)adapterDomain.CreateInstanceFrom(this.AdapterFilePath, this.AdapterFullName);
    (b)adapterAssembly=adapterDomain.Load(AssemblyName.GetAssemblyName(this.AdapterFilePath));
    

    If I use method (a), because the target class is a static one, it doesn't work.

    If I use method (b), because the target .dll is not the same directory with my project, I will get an exception.

How can I load the .dll and the static class, and then unload the .dll after my usage?

解决方案

Method (b) fails because AppDomain.Load cannot resolve assemblies that are not in the base app dir, the probing private paths or the GAC.

Also note that the AppDomain.Load is not loading the assembly on the specific AppDomain (like adapterDomain.Load in your sample code). Instead it is loading it on the current AppDomain (this is the one making the call to AppDomain.Load. This behavior is remarked on the MSDN documentation.) Apparently this is not what you are looking for.

Here's an example on how to call a static method in the child AppDomain:

class Program
{
    static void Main(string[] args)
    {
        // This is for testing purposes!
        var loadedAssembliesBefore = AppDomain.CurrentDomain.GetAssemblies();

        var domain = AppDomain.CreateDomain("ChildDomain");                        
        // This will make the call to the static method in the dhild AppDomain.
        domain.DoCallBack(LoadAssemblyAndCallStaticMethod);
        // Print the loaded assemblies on the child AppDomain. This is for testing purposes!
        domain.DoCallBack(PrintLoadedAssemblies);
        AppDomain.Unload(domain);

        // This is for testing purposes!
        var loadedAssembliesAfter = AppDomain.CurrentDomain.GetAssemblies();
        // Assert that no assembly was leaked to the main AppDomain.
        Debug.Assert(!loadedAssembliesBefore.Except(loadedAssembliesAfter).Any());

        Console.ReadKey();
    }

    // Loads StaticMethodInHere.dll to the current AppDomain and calls static method 
    // StaticClass.DoSomething.  
    static void LoadAssemblyAndCallStaticMethod()
    {
        var assembly = Assembly.LoadFrom(@"PATH_TO_ASSEMBLY");

        assembly.GetType("CLASS_CONTAINING_STATIC_METHOD")
                .InvokeMember("STATIC_METHOD", 
                              BindingFlags.Public | 
                              BindingFlags.Static | 
                              BindingFlags.InvokeMethod, 
                              null, 
                              null, 
                              null);
    }

    // Prints the loaded assebmlies in the current AppDomain. For testing purposes.
    static void PrintLoadedAssemblies()
    {
        Console.WriteLine("/ Assemblies in {0} -------------------------------",
                          AppDomain.CurrentDomain.FriendlyName);

        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            Console.WriteLine(assembly.FullName);
        }            
    }
}

To make this work you will need to replace:

  • PATH_TO_ASSEMBLY with the path of the assembly containing the static method including the extension.
  • CLASS_CONTAINING_STATIC_METHOD with the name of the class containing the static method including the namespace of the class.
  • STATIC_METHOD with the name of the static method.

Note that the BindingFlags are set for public static methods.

这篇关于在应用程序域中加载静态类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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