我正在尝试通过将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");
你发生了什么事吗?或者一些解决方法?
谢谢!
答案 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
在两个应用程序域中都可用,那么您应该看看:
答案 1 :(得分:0)
那么,
执行此代码时,FooProperty 没有初始化 Domain_AssemblyResolve事件
似乎没有任何代码在处理程序中初始化Foo
。
ClassLoader实例有一个 来自“c”的不同哈希码。
从Object继承的类的实例(如ClassLoader
)并且不重新实现GetHashCode()
,就像你的情况一样,都会有不同的哈希码(基于对象的地址)。如果您想要基于内部状态的一致代码,请覆盖GetHashCode()
。