首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Assembly.LoadFrom()或Assembly.Load()能够删除文件

Assembly.LoadFrom()或Assembly.Load()能够删除文件
EN

Stack Overflow用户
提问于 2017-01-02 12:04:11
回答 1查看 904关注 0票数 0

我的目标是:编写一个v6 (Visual扩展),其中我想编译一个项目,然后加载生成的.dll并通过反射检查它。由于代码是如何编写的,我无法使用ReflectionOnlyLoad()。如果我只执行Assembly.Load,那么文件将被锁定,直到用户重新启动整个IDE。

我正在尝试根据我在网上找到的样本建立一个单独的AppDomain。

它的要点是: 1.我创建了一个代理类,用于封送跨AppDomain实例的数据:

代码语言:javascript
运行
复制
internal class AppDomainProxy : MarshalByRefObject
    {
        public Assembly GetAssembly(string assemblyPath)
        {
            return Assembly.LoadFile(assemblyPath);
        }
}

然后,我创建了一个实例:

代码语言:javascript
运行
复制
var domaininfo = new AppDomainSetup { ApplicationBase = System.Environment.CurrentDirectory, ShadowCopyDirectories = "true", ShadowCopyFiles = "true", LoaderOptimization = LoaderOptimization.MultiDomainHost };

            var adevidence = System.AppDomain.CurrentDomain.Evidence;
            var domain = System.AppDomain.CreateDomain("reflection", adevidence, domaininfo);

             var proxyType = new AppDomainProxy().GetType();

            var proxyInstance = (AppDomainProxy)domain.CreateInstanceFromAndUnwrap(proxyType.Assembly.Location, proxyType.FullName);

            var loadedAssembly = (proxyInstance as AppDomainProxy).GetAssembly(this._assemblyLocation);

这无法将透明代理转换为我的AppDomainProxy类型。要解决这个问题,可以很容易地提供如下所示的程序集解析器:

代码语言:javascript
运行
复制
            this.domain.AssemblyResolve += CurrentDomainOnAssemblyResolve;

private Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
        {
            var loadedAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();

            foreach (var assembly in loadedAssemblies)
            {
                if (assembly.FullName == args.Name)
                {
                    return assembly;
                }
            }

            return null;
        }

这很好,我的代理被投出去了。但是,当我调用我的方法时,会再次调用CurrentDomainOnAssemblyResolve,这意味着Assembly属性实际上不是可序列化的,因此.net只是试图在原始端加载程序集,从而导致与Assembly.Load相同的问题。这很容易看到,因为像return AppDomain.Current.FriendlyName;这样简单的微软示例工作得很好。

更新作为一个解决方案,我只是移动了我的代码,需要程序集在另一边运行(在域内),然后返回字符串,它可以很好地封送。不过,我会保留这个问题,因为我想知道是否有解决实际问题的办法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-02 13:02:28

当然,您需要将处理程序集的代码移动到单独的AppDomain。这没有什么神奇之处--如果您需要处理来自引用程序集的类型,则需要加载该程序集。

AppDomain边界(和其他远程处理场景)编组对象的主要方法有两种:要么创建对象的副本,要么封送所有方法调用。这两种方法都非常棘手--您必须确保不会泄漏引用程序集中的类型,否则需要将其加载到两个域中。在您的示例中,您不能封送方法调用,因为Assembly不是(也不能是)一个MarshalByRefObject --您的代理必须返回一个真实的Assembly对象,并且不能创建编组代理。

要获得适当的隔离,必须避免从不希望共享的程序集中泄漏任何类型,以及可能公开其中任何类型的不可封送处理类型。这通常意味着如果您负担得起共享库中的原语和类型的话。保持一个良好的紧密接口,不要过多地利用“自动”编组--将自动代理返回到复杂对象是很方便的,但会使理解接口的范围变得更加困难。对象是否有从非共享程序集返回类型的方法?太糟糕了,您也需要在您的域中加载它。

通常,使用实际互操作的多个AppDomains (以及相关的.NET远程处理)是一个巨大的痛苦。它很复杂,容易出错,而且很难纠正。你可以阅读关于这一主题的整本书。不再推荐使用它们是有原因的,也是PCL不支持它们的原因(而且很长一段时间以来,Mono不支持它们)。它们还有用吗?嗯。软件隔离有非常好的好处。但是你需要非常小心,不要把事情搞砸:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41426509

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档