在另一个代理中包装 RemotingProxy 的 __TransparentProxy 抛出 RemotingException
Wrapping __TransparentProxy of RemotingProxy in another Proxy throws RemotingException
目标
我有几个接口和一些为这些接口提供实现的 dll。我想将实现加载到新的 AppDomain 中(这样我可以稍后卸载 dll)并在新的 AppDomain 中实例化实现,然后使用客户端(这里是默认的 AppDomain)代理来包装实际的实现对象。目标是创建这些 ClientProxy
个实例一次,并在不将实现程序集加载到默认 AppDomain 的情况下随时更改它们的实际实现。
问题
当在 ClientProxy __TransparentProxy 对象上调用方法时,将另一个 ClientProxy 作为参数,我得到以下异常:
System.Runtime.Remoting.RemotingException:
'The argument type 'System.MarshalByRefObject' cannot be converted into parameter type 'IData'.'
有内部异常:
InvalidCastException: Object must implement IConvertible.
传递直接从 Server AppDomain 获取的 __TransparentProxy 时,ClientProxy 起作用。
设置
可克隆自:https://github.com/mailgerigk/remoting
接口:
public interface IData
{
int Foo { get; set; }
}
public interface ILogic
{
void Update(IData data);
}
_impl.dll 中的接口实现:
public class DataImpl : MarshalByRefObject, IData
{
public int Foo { get; set; }
}
public class LogicImpl : MarshalByRefObject, ILogic
{
public void Update(IData data)
{
data.Foo++;
}
}
服务器端程序集加载器:
class AssemblyLoader : MarshalByRefObject
{
public Assembly Assembly { get; private set; }
public AssemblyLoader(string assemblyFile)
{
Assembly = Assembly.LoadFrom(assemblyFile);
}
public object CreateInstance(string typeName)
{
return Activator.CreateInstance(Assembly.GetType(typeName));
}
}
客户端代理:
class ClientProxy : RealProxy
{
private RealProxy innerProxy;
public ClientProxy(Type interfaceType, object proxyObject)
: base(interfaceType)
{
SetInnerProxy(proxyObject);
}
public void SetInnerProxy(object proxyObject)
{
innerProxy = RemotingServices.GetRealProxy(proxyObject);
}
public override IMessage Invoke(IMessage msg)
{
return innerProxy.Invoke(msg);
}
}
主要:
class Program
{
static void Main(string[] args)
{
var app = AppDomain.CreateDomain("ImplDomain", null,
AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.RelativeSearchPath,
true);
var assmblyLoader = app.CreateInstanceFromAndUnwrap(
typeof(AssemblyLoader).Assembly.Location, typeof(AssemblyLoader).FullName,
false, BindingFlags.CreateInstance, null,
new object[]
{
"_impl.dll"
},
null, null) as AssemblyLoader;
var dataImpl = assmblyLoader.CreateInstance("DataImpl") as IData;
var logicImpl = assmblyLoader.CreateInstance("LogicImpl") as ILogic;
logicImpl.Update(dataImpl); // Works
Console.WriteLine(dataImpl.Foo); // prints 1
var clientDataProxy = new ClientProxy(typeof(IData), dataImpl);
var clientDataImpl = clientDataProxy.GetTransparentProxy() as IData;
var clientLogicProxy = new ClientProxy(typeof(ILogic), logicImpl);
var clientLogicImpl = clientLogicProxy.GetTransparentProxy() as ILogic;
clientLogicImpl.Update(dataImpl); // Works
Console.WriteLine(clientDataImpl.Foo); // prints 2
clientLogicImpl.Update(clientDataImpl); // throws System.Runtime.Remoting.RemotingException
Console.WriteLine(clientDataImpl.Foo);
}
}
在不知道你的推理的情况下,从提供的示例代码来看,ClientProxy class 似乎是不必要的,因为你可以通过直接使用 RealProxy
获得相同的行为:
var clientDataProxy = RemotingServices.GetRealProxy(dataImpl);
也就是说,您当然可以创建自己的具体 RealProxy
并让它按预期工作 - 您只是缺少从 innerProxy
:[=20 获取 TransparentProxy 的覆盖=]
class ClientProxy : RealProxy
{
... everything else ...
public override object GetTransparentProxy() => innerProxy.GetTransparentProxy();
public object GetOuterTransparentProxy() => base.GetTransparentProxy();
}
...
var clientDataProxy = new ClientProxy(typeof(IData), dataImpl);
var clientDataImpl = clientDataProxy.GetOuterTransparentProxy() as IData;
var clientLogicProxy = new ClientProxy(typeof(ILogic), logicImpl);
var clientLogicImpl = clientLogicProxy.GetOuterTransparentProxy() as ILogic;
...
就目前而言,您的 ClientProxy
正在向外部对象返回 TransparentProxy
。
编辑: 根据评论中的解释,我添加了一个辅助 GetOuterTransparentProxy
方法,即 returns 外部基础实现。这仍然允许使用 OOTB RealProxy.Invoke
实现,同时公开要重用的外部 TransparentProxy
。
目标
我有几个接口和一些为这些接口提供实现的 dll。我想将实现加载到新的 AppDomain 中(这样我可以稍后卸载 dll)并在新的 AppDomain 中实例化实现,然后使用客户端(这里是默认的 AppDomain)代理来包装实际的实现对象。目标是创建这些 ClientProxy
个实例一次,并在不将实现程序集加载到默认 AppDomain 的情况下随时更改它们的实际实现。
问题
当在 ClientProxy __TransparentProxy 对象上调用方法时,将另一个 ClientProxy 作为参数,我得到以下异常:
System.Runtime.Remoting.RemotingException:
'The argument type 'System.MarshalByRefObject' cannot be converted into parameter type 'IData'.'
有内部异常:
InvalidCastException: Object must implement IConvertible.
传递直接从 Server AppDomain 获取的 __TransparentProxy 时,ClientProxy 起作用。
设置
可克隆自:https://github.com/mailgerigk/remoting
接口:
public interface IData
{
int Foo { get; set; }
}
public interface ILogic
{
void Update(IData data);
}
_impl.dll 中的接口实现:
public class DataImpl : MarshalByRefObject, IData
{
public int Foo { get; set; }
}
public class LogicImpl : MarshalByRefObject, ILogic
{
public void Update(IData data)
{
data.Foo++;
}
}
服务器端程序集加载器:
class AssemblyLoader : MarshalByRefObject
{
public Assembly Assembly { get; private set; }
public AssemblyLoader(string assemblyFile)
{
Assembly = Assembly.LoadFrom(assemblyFile);
}
public object CreateInstance(string typeName)
{
return Activator.CreateInstance(Assembly.GetType(typeName));
}
}
客户端代理:
class ClientProxy : RealProxy
{
private RealProxy innerProxy;
public ClientProxy(Type interfaceType, object proxyObject)
: base(interfaceType)
{
SetInnerProxy(proxyObject);
}
public void SetInnerProxy(object proxyObject)
{
innerProxy = RemotingServices.GetRealProxy(proxyObject);
}
public override IMessage Invoke(IMessage msg)
{
return innerProxy.Invoke(msg);
}
}
主要:
class Program
{
static void Main(string[] args)
{
var app = AppDomain.CreateDomain("ImplDomain", null,
AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.RelativeSearchPath,
true);
var assmblyLoader = app.CreateInstanceFromAndUnwrap(
typeof(AssemblyLoader).Assembly.Location, typeof(AssemblyLoader).FullName,
false, BindingFlags.CreateInstance, null,
new object[]
{
"_impl.dll"
},
null, null) as AssemblyLoader;
var dataImpl = assmblyLoader.CreateInstance("DataImpl") as IData;
var logicImpl = assmblyLoader.CreateInstance("LogicImpl") as ILogic;
logicImpl.Update(dataImpl); // Works
Console.WriteLine(dataImpl.Foo); // prints 1
var clientDataProxy = new ClientProxy(typeof(IData), dataImpl);
var clientDataImpl = clientDataProxy.GetTransparentProxy() as IData;
var clientLogicProxy = new ClientProxy(typeof(ILogic), logicImpl);
var clientLogicImpl = clientLogicProxy.GetTransparentProxy() as ILogic;
clientLogicImpl.Update(dataImpl); // Works
Console.WriteLine(clientDataImpl.Foo); // prints 2
clientLogicImpl.Update(clientDataImpl); // throws System.Runtime.Remoting.RemotingException
Console.WriteLine(clientDataImpl.Foo);
}
}
在不知道你的推理的情况下,从提供的示例代码来看,ClientProxy class 似乎是不必要的,因为你可以通过直接使用 RealProxy
获得相同的行为:
var clientDataProxy = RemotingServices.GetRealProxy(dataImpl);
也就是说,您当然可以创建自己的具体 RealProxy
并让它按预期工作 - 您只是缺少从 innerProxy
:[=20 获取 TransparentProxy 的覆盖=]
class ClientProxy : RealProxy
{
... everything else ...
public override object GetTransparentProxy() => innerProxy.GetTransparentProxy();
public object GetOuterTransparentProxy() => base.GetTransparentProxy();
}
...
var clientDataProxy = new ClientProxy(typeof(IData), dataImpl);
var clientDataImpl = clientDataProxy.GetOuterTransparentProxy() as IData;
var clientLogicProxy = new ClientProxy(typeof(ILogic), logicImpl);
var clientLogicImpl = clientLogicProxy.GetOuterTransparentProxy() as ILogic;
...
就目前而言,您的 ClientProxy
正在向外部对象返回 TransparentProxy
。
编辑: 根据评论中的解释,我添加了一个辅助 GetOuterTransparentProxy
方法,即 returns 外部基础实现。这仍然允许使用 OOTB RealProxy.Invoke
实现,同时公开要重用的外部 TransparentProxy
。