在创建的AppDomain上AssemblyResolve事件的问题

时间:2010-06-30 10:26:46

标签: c# .net appdomain assembly-resolution

我正在尝试通过将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;
    }
    // ...
}

执行此代码时,未在Domain_AssemblyResolve事件处理程序中初始化FooProperty,并且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");

你发生了什么事吗?或者一些解决方法?

谢谢!

2 个答案:

答案 0 :(得分: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在两个应用程序域中都可用,那么您应该看看:

Making Objects Remotable

Events and Delegates with .NET Framework Remoting

答案 1 :(得分:0)

那么,

  

执行此代码时,FooProperty   没有初始化   Domain_AssemblyResolve事件

似乎没有任何代码在处理程序中初始化Foo

  

ClassLoader实例有一个   来自“c”的不同哈希码。

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