2

我正在尝试通过将AppDomain其及其AssemblyResolve事件包装在一个类中来自定义程序集解析过程。我的简化版ClassLoader如下。我遇到的问题是,当事件AssemblyResolve被触发时,似乎我得到了一个新的实例ClassLoader,而不是我之前创建的那个。

[Serializable]
public class ClassLoader // : IDisposable
{
    public AppDomain Domain { get; private set; }
    public string FooProperty { get; set; }

    public ClassLoader(string domain) {
        Domain = AppDomain.CreateDomain(domain);
        Domain.AssemblyResolve += Domain_AssemblyResolve;
    }

    private Assembly Domain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        Console.WriteLine(
            "ClassLoader HashCode: {0} FooProperty: {1}\n\n", 
            GetHashCode(), 
            FooProperty);
        // ...
        return null;
    }
    // ...
}

执行此代码时,FooProperty 未在 Domain_AssemblyResolve 事件处理程序中初始化,并且 ClassLoader 实例具有与“c”不同的哈希码。

 var c = new ClassLoader("demo");
 c.FooProperty = "Foo";
 Console.WriteLine(
     "c Hash Code: {0} FooProperty: {1}", 
     c.GetHashCode(), 
     c.FooProperty);
 c.Domain.CreateInstanceAndUnwrap("Not important", "Not important");

你知道发生了什么吗?或一些解决方法?

谢谢!

4

2 回答 2

2

ClassLoader实例c是在应用程序域上创建的,A并且由于它没有从MarshalByRefObject它继承,因此它将被序列化到您在将事件处理程序添加到时创建的应用程序域中AssemblyResolve。发生这种情况是因为该方法是实例方法,并且委托将需要对将调用该方法的目标对象的引用。

如果您只希望在FooProperty触发事件处理程序时具有特定值,那么您只能在初始化属性后添加事件处理程序,导致值被序列化并在新创建的应用程序域中可用。

public string FooProperty { get; private set; }

public ClassLoader(string domain, string fooProperty)
{
    FooProperty = fooProperty; // Set it before adding event handler
    Domain = AppDomain.CreateDomain(domain);
    Domain.AssemblyResolve += Domain_AssemblyResolve;
}

如果您要求实例c在两个应用程序域中都可用,那么您应该查看:

使对象可远程

使用 .NET Framework 远程处理的事件和委托

于 2010-06-30T10:55:44.497 回答
0

好,

执行此代码时,FooProperty 未在 Domain_AssemblyResolve 事件中初始化

似乎没有任何代码Foo在处理程序内部进行初始化。

ClassLoader 实例具有与“c”不同的哈希码。

从 Object 继承(如ClassLoader)并且不重新实现的GetHashCode()类的实例,如您的情况,都将具有不同的哈希码(基于对象的地址)。GetHashCode()如果您想要基于内部状态的一致代码,请覆盖。

于 2010-06-30T10:35:54.067 回答