所以情况就是这样 - 我有一个派生自抽象基类的类(因此不能派生MarshalByRefObject并用作代理对象)并且它具有正确的状态是很重要的,因为它正在处理用流和做一些重要的事情。
它标记为Serializable,因为我需要将其传递到另一个AppDomain并让该appdomain定期调用.Post(string)
方法。
我不知道有关appdomains的一切,但我看到一些奇怪的事情,我假设该类实际上在第二个AppDomain中使用相同的字段和属性重新实例化,然后我最终得到了多个实例该课程。
这是一个问题,因为当第二个AppDomain调用.Post()
时,它会对流进行修改,并且它自己的对象状态,但主应用程序域中类中包含的私有变量不会更新 - 所以主应用程序域中存在损坏的状态,一旦主应用程序域在其自己的类版本上调用.Post
,我就会遇到损坏的流!
我也不能使用包装类,因为我需要传递作为其抽象基类的对象,第二个appdomain不知道派生类的类型是什么,只知道调用{ {1}}这是在基类中定义的抽象方法。
有没有办法可以将第二个appdomain对该类所做的更改更新回命令的主appdomain字段,以便我可以“同步”字段的状态,这样可以说呢?
答案 0 :(得分: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
包装类,该类派生自MarshalByRefObject
并实现IFoo
/// <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
方法。
执行该程序的输出: