0

所以情况就是这样——我有一个派生自抽象基类的类(因此不能从 MarshalByRefObject 派生并用作代理对象),并且它具有正确的状态很重要,因为它正在处理流并做一些重要的事情。

它被标记为 Serializable 因为我需要将它传递给另一个 AppDomain 并让该 appdomain 定期调用一个.Post(string)方法。

我对appdomains一无所知,但我看到了一些奇怪的事情,我假设该类实际上在第二个AppDomain中使用相同的字段和属性重新实例化,然后我最终得到了该类的多个实例.

这是一个问题,因为当第二个 AppDomain 调用时.Post(),它对流和它自己的对象状态进行了修改,但是主应用程序域中的类中包含的私有变量没有更新 - 所以主应用程序域中存在损坏的状态一旦主应用程序域调用.Post它自己的类版本,appdomain 和我就会得到一个损坏的流!

我也不能使用包装类,因为我需要传递作为其抽象基类的对象,而第二个 appdomain 不知道派生类的类型是什么,只知道调用.Post哪个是抽象类基类中定义的方法。

有什么方法可以将第二个 appdomain 对类所做的更改更新回命令上的主 appdomain 字段,以便我可以“同步”这些字段的状态?

4

1 回答 1

1

我认为您可以使用MarshalByRefObject包装类来完成这项工作。

考虑以下示例:

using System;
using System.IO;
using System.Reflection;

namespace ConsoleApplication13
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain appDomain = AppDomain.CreateDomain("foo");

            FooFactory fooFactory = (FooFactory)appDomain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, typeof(FooFactory).FullName);

            IFoo fooFromOtherDomain = fooFactory.CreateMeAFoo();

            string message = "Hello World!";

            Console.WriteLine("Data = {0} on AppDomain ID = {1}", message, AppDomain.CurrentDomain.Id);

            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(message);
            fooFromOtherDomain.Post(buffer);
        }
    }

    public interface IFoo
    {
        void Post(byte[] data);
    }

    public abstract class FooBase
    {}

    /// <summary>
    /// This class represents your class that can't be marshaled by ref...
    /// </summary>
    public class Foo : FooBase, IFoo, IDisposable
    {
        private MemoryStream _buffer;

        public Foo()
        {
            this._buffer = new MemoryStream();
        }

        public void Post(byte[] data)
        {
            if (data == null)
                throw new ArgumentNullException("data");

            this._buffer.Seek(0, SeekOrigin.End);
            this._buffer.Write(data, 0, data.Length);

            OnNewData();
        }

        private void OnNewData()
        {
            string dataString = System.Text.Encoding.UTF8.GetString(this._buffer.ToArray());
            Console.WriteLine("Data = {0} on AppDomain ID = {1}", dataString, AppDomain.CurrentDomain.Id);
        }

        public void Dispose()
        {
            this._buffer.Close();
        }
    }

    /// <summary>
    /// Wraps the non-remote Foo class and makes it remotely accessible.
    /// </summary>
    public class FooWrapper : MarshalByRefObject, IFoo
    {
        private IFoo _innerFoo;

        public FooWrapper(IFoo innerFoo)
        {
            this._innerFoo = innerFoo;
        }

        public void Post(byte[] data)
        {
            this._innerFoo.Post(data);
        }
    }

    /// <summary>
    /// For demo purposes to get an instance of IFoo from the other domain.
    /// </summary>
    public class FooFactory : MarshalByRefObject
    {
        public IFoo CreateMeAFoo()
        {
            Foo foo = new Foo();
            FooWrapper fooWrapper =new FooWrapper(foo);

            return fooWrapper;
        }
    }
}

不要太在意 FooFactory 类。那只是为了让远程创建一个展示您的场景的对象变得容易。

本质上为您的远程类定义一个接口,例如IFoo.

public interface IFoo
{
    void Post(byte[] data);
}

创建一个派生自并实现的Foo包装类MarshalByRefObjectIFoo

/// <summary>
/// Wraps the non-remote Foo class and makes it remotely accessible.
/// </summary>
public class FooWrapper : MarshalByRefObject, IFoo
{
    private IFoo _innerFoo;

    public FooWrapper(IFoo innerFoo)
    {
        this._innerFoo = innerFoo;
    }

    public void Post(byte[] data)
    {
        this._innerFoo.Post(data);
    }
}

将您的 IFoo 实现传递给FooWrapper.

Foo foo = new Foo();
FooWrapper fooWrapper = new FooWrapper(foo);

然后像往常一样返回FooWrapper到另一个域并调用IFoo方法。Post

该程序的执行输出:

在此处输入图像描述

于 2013-06-24T17:36:33.000 回答