创建的 AppDomain 上的 AssemblyResolve 事件出现问题

发布于 2024-09-07 06:16:25 字数 1225 浏览 10 评论 0原文

我试图通过将 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");

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

谢谢!

I am trying to customize the assembly resolution process by wrapping the AppDomain and its AssemblyResolve event inside a class. The simplified version of my ClassLoader is below. The problem I am having is that when the event AssemblyResolve is fired, it seems that I get a new instance of ClassLoader, not the one I previously created.

[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;
    }
    // ...
}

When executing this code, FooProperty is not initialized in the Domain_AssemblyResolve event handler and the ClassLoader instance has a different hash code from "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");

Do you what is happening? or some workaround?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听你说爱我 2024-09-14 06:16:25

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 远程处理的事件和委托

The ClassLoader instance c is created on application domain A and since it does not inherits from MarshalByRefObject it will be serialized into the application domain that you are creating at the moment you add the event handler to AssemblyResolve. This happens because the method is an instance method and the delegate will need a reference to the target object where the method will be called.

If you just want that the FooProperty have a specific value when the event handler is triggered then you can add the event handler only after initializing the property causing the value to be serialized and available in the newly created application domain.

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;
}

If you have the requirement that the instance c is available in both application domains then you should take a look at:

Making Objects Remotable

Events and Delegates with .NET Framework Remoting

叹沉浮 2024-09-14 06:16:25

出色地,

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

处理程序内似乎没有任何初始化 Foo 的代码。

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

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

Well,

When executing this code, FooProperty
is not initialized in the
Domain_AssemblyResolve event

There doesn't seem to be any code that initialises Foo inside the handler.

the ClassLoader instance has a
different hash code from "c".

Instances of classes that inherit from Object (like ClassLoader) and don't reimplement GetHashCode(), like in your case, will all have different hash codes (based on the address of the object). Override GetHashCode() if you want consistent codes based on internal state.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文