首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过MarshalByRefObject边界传递强类型的AppDomain?

如何通过MarshalByRefObject边界传递强类型的AppDomain?
EN

Stack Overflow用户
提问于 2015-06-15 19:23:12
回答 1查看 712关注 0票数 0

我有一个场景,希望在父AppDomain与其子级之间实现简单的通信。我想要做的事情看起来很管用,但我遇到了一个麻烦,下面的片段就是一个例子。

程序的结果是为C::.ctor(System.MarshalByRefObject)找到message构造函数,因此运行时似乎拒绝了构造函数,它接受了我要传递给CreateInstanceFromAndUnwrap调用的类型的参数。我可以理解为什么实例化B工作,并且我期望C的行为是相同的,那么为什么它不能呢?

谢谢!

编辑:汉斯在我的第一个例子中指出了一个普通的错误之后,我对下面的示例代码做了一个小的更新。因此,虽然在我们的子应用程序域上仍然有一个虚构的ApplicationBase属性,但是我们可以看到正确的程序集被加载,并且我们试图调用的构造函数可以被看到。

汉斯的观察确实使代码工作,但我认为我不能将真实的ApplicationBase设置为父域的基础。

循环的第二次迭代的输出现在如下:

C

初始加载: mscorlib

解封后: mscorlib

解封后: Foo

真空.ctor(A)

构造函数在类型'C‘上找不到。

代码语言:javascript
复制
using System;
using System.Linq;
using System.Reflection;

class A : MarshalByRefObject { }

class B : MarshalByRefObject
{
    public B(MarshalByRefObject obj) { }
}

class C : MarshalByRefObject
{
    public C(A obj) { }
}

static class Program
{
    static void Main(string [] args)
    {
        foreach (var type in new [] { typeof(B), typeof(C) })
        {
            try
            {
                Console.WriteLine(type.FullName);

                var setup = CreateSetup();

                var domain = AppDomain.CreateDomain("foo", AppDomain.CurrentDomain.Evidence, setup);

                foreach (var ass in domain.GetAssemblies())
                {
                    Console.WriteLine("Initially Loaded: {0}", ass.GetName().Name);
                }

                domain.CreateInstanceFromAndUnwrap(typeof(A).Assembly.Location, typeof(A).FullName);

                foreach (var ass in domain.GetAssemblies())
                {
                    Console.WriteLine("After Unwrap: {0}", ass.GetName().Name);
                }

                var constructors = domain.GetAssemblies()
                    .ToList()
                    .SelectMany(ass => ass.DefinedTypes)
                    .First(t => t.Name == "C")
                    .GetConstructors();

                foreach (var constructor in constructors)
                {
                    Console.WriteLine(constructor);
                }

                CreateWrapped(domain, type);

                AppDomain.Unload(domain);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    static AppDomainSetup CreateSetup()
    {
        return new AppDomainSetup
        {
            ApplicationBase = "foo",
            ApplicationName = "bar",
            DisallowBindingRedirects = false,
            ConfigurationFile = "baz",
            LoaderOptimization = LoaderOptimization.MultiDomainHost
        };
    }

    static object CreateWrapped(AppDomain domain, Type type)
    {
        return domain.CreateInstanceFromAndUnwrap(
            assemblyFile: type.Assembly.Location,
            typeName: type.FullName,
            ignoreCase: false,
            bindingAttr: BindingFlags.Default,
            binder: null,
            args: new object[] { new A() },
            culture: null,
            activationAttributes: null
        );
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-28 19:13:39

正如汉斯指出的那样,问题是我的CreateSetup函数中的CreateSetup,我在这里修正了这个问题:

代码语言:javascript
复制
static AppDomainSetup CreateSetup()
{
    return new AppDomainSetup
    {
        ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
        ApplicationName = "bar",
        DisallowBindingRedirects = false,
        ConfigurationFile = "baz",
        LoaderOptimization = LoaderOptimization.MultiDomainHost
    };
}

通过这种修改,示例程序将在其子域中实例化BC,从而正确执行。

我执行的强制程序集加载在此更改之后并不是必要的,尽管我仍然无法解释为什么子应用程序域在首先构建一个C对象以加载所需的程序集之后无法解析A构造函数。

我最好的解释是,使用默认的负载上下文与为其基指定的无效路径的应用程序域一起使用会导致C探测时的解析失败。

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

https://stackoverflow.com/questions/30853361

复制
相关文章

相似问题

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