【问题标题】:Load and Unload Assembly in own AppDomain在自己的 AppDomain 中加载和卸载程序集
【发布时间】:2013-10-27 07:59:18
【问题描述】:

我做网络。通过输入参数加载程序集文件的服务。 然后在汇编中会尝试查找特定类型(继承自特定接口),创建实例并返回方法的结果。

我需要调用的程序集再次被释放。

从方法的输入参数中,我在 web.config 中找到程序集的路径。并尝试加载它。

这是有效的代码:

[WebMethod]
    public String[] GetData(String confKey)
    {
        var assemblyPath = ConfigurationManager.AppSettings[confKey];
        var assembly = Assembly.LoadFrom(assemblyPath);

        List<String> retVals = new List<String>();

        foreach (var t in assembly.GetTypes())
        {
            if (t.ImplementsInterface(typeof(IMyServiceProvider)))
            {
                IMyServiceProvider objectInstance = Activator.CreateInstance(t) as IMyServiceProvider;
                retVals.Add(objectInstance.GetData());
            }
        }

        return retVals.ToArray();
    }

但是这样我可以删除加载的程序集或替换它,因为文件被“锁定”了。

所以我尝试采用不同的方式将程序集加载到自己的 AppDomain 中,如下所示:

[WebMethod]
    public String[] GetData(String confKey)
    {
        var assemblyPath = ConfigurationManager.AppSettings[confKey];

        var tmp = String.Concat("AppDomain", Guid.NewGuid().ToString("N"));
        AppDomain dom = AppDomain.CreateDomain(tmp, null, AppDomain.CurrentDomain.SetupInformation);
        AssemblyName assemblyName = new AssemblyName();
        assemblyName.CodeBase = assemblyPath;
        Assembly assembly = dom.Load(assemblyPath);

        List<String> retVals = new List<String>();

        foreach (var t in assembly.GetTypes())
        {
            if (t.ImplementsInterface(typeof(IMyServiceProvider)))
            {
                IMyServiceProvider objectInstance = Activator.CreateInstance(t) as IMyServiceProvider;
                retVals.Add(objectInstance.GetData());
            }
        }

        AppDomain.Unload(dom);
        return retVals.ToArray();
    }

但是这个解决方案抛出异常:

无法加载文件或程序集“NameOfMyAssembly”或其依赖项之一。给定的程序集名称或代码库无效。 (来自 HRESULT 的异常:0x80131047)- 在 System.Reflection.AssemblyName.nInit(RuntimeAssembly 和程序集,布尔 forIntrospection,布尔 raiseResolveEvent) 在 System.Reflection.RuntimeAssembly.CreateAssemblyName(字符串 assemblyString,布尔 for Introspection,RuntimeAssembly 和 assemblyFromResolveEvent) 在 System.Reflection.RuntimeAssembly.InternalLoad(字符串 assemblyString,证据 assemblySecurity,StackCrawlMark 和 stackMark,IntPtr pPrivHostBinder,Boolean forIntrospection) 在 System.Reflection.RuntimeAssembly.InternalLoad(字符串 assemblyString,证据 assemblySecurity,StackCrawlMark 和 stackMark,Boolean for Introspection) 在 System.AppDomain.Load(字符串 assemblyString) 在 System.AppDomain.Load(String assemblyString)

为什么第一个解决方案程序集加载没有问题,而第二个则抛出错误? 谢谢

【问题讨论】:

  • 为什么不使用 MEF 并动态加载所有库?

标签: c# web-services


【解决方案1】:

dom.Load(string) 方法尝试按其全名加载程序集,该全名由程序集名称、版本、文化信息和公钥组成。 CLR 在 GAC 和应用程序目录中搜索程序集。您还可以使用 .config 文件(app.config 或 )和 probing 元素设置其他搜索路径。在您的情况下,据我了解 assemblyPath 是您要加载的程序集的路径,它不需要作为参数传递。我使用下一个代码在创建的域中加载程序集:

var domain = AppDomain.CreateDomain("Plugin domain"); // Domain for plugins
domain.Load(typeof(IPlugin).Assembly.FullName); // Load assembly containing plugin interface to domain 
// ...

var asm = Assembly.LoadFrom(pluginFile);
foreach (var exportedType in asm.GetExportedTypes())
{
    if (!typeof (IPlugin).IsAssignableFrom(exportedType))
        continue; // Check if exportedType implement IPlugin interface
    domain.Load(asm.FullName); // If so load this dll into domain
    // ...
}

由于所有插件都位于“\Plugins”目录中,相对于应用程序目录,我还添加了 .config 文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="Plugins"/>
    </assemblyBinding>
  </runtime>
</configuration>

请注意,如果您想使用 dom.Load(AssemblyName) 并仅指定 CodeBase 属性,则必须将其设置为 Uri 格式(即“file:///D:/Dir/. .."),我认为如果这些程序集不在当前应用程序的文件夹中,则必须对其进行强命名。

我也看到你使用 Activator.CreateInstance() 来创建对象。在这种情况下,尽管您在创建的域中加载程序集,但您在当前域中创建对象,并且该对象的所有代码也将在当前域中执行。要在单独的域中创建和执行代码,您应该使用 appDomain.CreateInstanceAndUnwrap() 方法 (link)

【讨论】:

    猜你喜欢
    • 2011-01-09
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    • 2010-09-12
    • 2011-02-12
    相关资源
    最近更新 更多