如何通过网络代理远程具有固定大小批次的 .NET IEnumerable?
.NET 远程处理可以为具有可序列化成员的接口生成透明代理远程,例如:
public interface INetworkInterface {
bool login(string username, string password);
bool ExecuteSomething(string command);
}
我想为任何 IEnumerator
返回结果提供自定义序列化程序和活动代理远程程序。我的自定义代理远程程序将通过网络一次处理特定数量的元素的批处理。例如,给定以下接口:
public interface INetworkInterface2 {
IEnumerable<string> ExecuteSomething(string command);
}
我想提供一个自定义序列化器和代理,它会在 IEnumerator
出现在远程接口中,并将 IEnumerator
序列化到具有 .NET 远程的客户端 EnumeratorBatchHandlerClient
- 服务器端 EnumeratorBatchHandlerServer
的代理。
我认为客户端批处理程序看起来像这样:
class EnumeratorBatchHandlerClient<T> : IEnumerable<T> {
List<T> batched_results = new List<T>();
EnumerableBatchHandlerServer server_proxy;
T cur = null;
bool MoveNext() {
if (batched_results.Count == 0) {
batched_results = server_proxy.getNextBatch().ToList();
if (batched_results.Count == 0) {
return false; // we are really out of results
}
}
cur = batched_results[0]; batched_results.RemoveAt(0);
return true;
}
public T Current { get { return cur; } }
}
当 IEnumerable 出现在代理接口中时,是否有一种方法可以使 .NET Remoting 透明地生成并链接我的自定义客户端/服务器“ienumerable 批处理代理”?
更新:我为此想到的一个巧妙的想法是构建一个 RealProxy
来完成插入存根的工作,并将其粘贴在我的远程类前面。我想如果我使客户端处理程序可序列化并且服务器处理程序 marshalbyref ,它会将客户端处理程序发送到客户端并让它与服务器处理程序远程通信。我构建了这样一个 RealProxy,并且每当它看到 IEnumerator
时,它都会忠实地实例化我的 EnumeratorClientBatchHandler<>
和 EnumeratorServerBatchHandler<>
。但是,我无法使用 .NET 远程处理“远程”RealProxy
,因为它不能是 MarshalByRefObject
和 RealProxy
的子类同时。
我看到的唯一前进道路是构建我自己的远程处理系统,该系统不需要接口实现成为 MarshalByRefObject 的子类来代理远程它们。我看不出有什么理由这是不可能的,因为 RealProxy 看起来可以代理任何接口类型。 (只有 .NET 远程处理会检查基础类型是否为 MarshalByRefObject)。作为一个附带好处,我认为拥有一个使用新的 C# 5.0 异步系统来允许异步处理程序为“标准”接口提供服务的远程处理系统会很好。
下面的这个 Q/A 似乎是半相关的,并讨论了将自定义序列化器 (protobuf) 与 WCF 结合使用。然而,这在一些方面与我正在寻找的不同。 (1) 它仍然将所有数据序列化为二进制流,没有像我上面所需要的“持续代理通道”来继续通过远程处理通道发出代理批量调用,(2) 转换返回结果的手动 WCF 模式EndpointAddress10 似乎与上述模式不兼容。
当然我知道我可以创建一个远程接口,它是批处理接口,然后让客户端手动处理批处理...或者让他们手动将批处理接口包装在自己的 EnumerableBatchHandlerClient 实例中。我试图弄清楚如何以透明的方式做到这一点,因为我将通过特定系统提供许多接口,IEnumerables 将非常常见,并且我希望远程处理能够“自动”任何看起来像基本数据类型调用或 IEnumerable (具有批处理支持)的东西。
.NET remoting can generate transparent proxy remotes for an interface with serializable members, such as:
public interface INetworkInterface {
bool login(string username, string password);
bool ExecuteSomething(string command);
}
I'd like to supply a custom serializer and active proxy-remoter for any IEnumerator<T>
return result. My custom proxy-remoter would handle batching a specific number of elements at a time over the network. For example, given the following interface:
public interface INetworkInterface2 {
IEnumerable<string> ExecuteSomething(string command);
}
I would like to supply a custom serializer AND proxy which is automatically used anytime an IEnumerator<T> where T:ISerializable
appears in a remoted interface, and would serialize IEnumerator<string>
into a client-side EnumeratorBatchHandlerClient<string>
which has a .NET remote-proxy to a server-side EnumeratorBatchHandlerServer<string>
.
I'm thinking the client-batch-handler would look something like this:
class EnumeratorBatchHandlerClient<T> : IEnumerable<T> {
List<T> batched_results = new List<T>();
EnumerableBatchHandlerServer server_proxy;
T cur = null;
bool MoveNext() {
if (batched_results.Count == 0) {
batched_results = server_proxy.getNextBatch().ToList();
if (batched_results.Count == 0) {
return false; // we are really out of results
}
}
cur = batched_results[0]; batched_results.RemoveAt(0);
return true;
}
public T Current { get { return cur; } }
}
Is there a way to cause .NET Remoting to transparently produce and link my custom client/server "ienumerable batch proxy" when IEnumerable appears in a proxied interface?
Update: One crafty idea I had for doing this was to build a RealProxy
that would do the work of inserting the stubs, and stick this in front of my remoted class. I figured if I made the client-handler serializable and the server-handler marshalbyref it would send the client-handler to the cilent-side and let it talk remotely to the server-handler. I built such a RealProxy, and it does faithfully instantiate my EnumeratorClientBatchHandler<>
and EnumeratorServerBatchHandler<>
anytime it sees an IEnumerator
. However, I can't "remote" the RealProxy
with .NET remoting, because it can't be a subclass of MarshalByRefObject
and RealProxy
at the same time.
The only path forward I see is to build my own remoting system which doesn't require interface implementations to be subclasses of MarshalByRefObject in order to proxy remote them. I don't see any reason this isn't possible, since it looks like RealProxy can proxy any interface type. (only .NET remoting is checking that the underlying type is MarshalByRefObject). As a side-benefit, I think it would be nice to have a remoting system that uses the new C# 5.0 async system to allow an async handler to service a "standard" interface.
This Q/A below seems semi-related, and talks about using a custom serializer (protobuf) with WCF. However, this is different than what I'm looking for in a few ways. (1) it still serializes all data to a binary stream, there is no 'ongoing proxy channel' such as I need above to continue to issue proxy-batch calls through the remoting channel, (2) The manual WCF pattern of translating return results to EndpointAddress10 seems incompatible with the above pattern.
How to use custom serialization during .NET remoting?
Of course I know I can make a remoting interface which IS the batching interface, and then make clients manually deal with batching... or have them manually wrap the batching interface in their own instance of the EnumerableBatchHandlerClient. I'm trying to figure out how to do this in a transparent way because I'm going to have many many interfaces vended through a particular system, IEnumerables will be very common, and I'd like the remoting to be 'automagic' for anything that looks like a basic-datatype call or an IEnumerable (with batch support).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论