如何用WCF/gRPC替代.NET Remoting实现远程对象属性的透明代理访问?
.NET Remoting迁移:实现远程对象代理(替代TransparentProxy)
你当前的需求是替代已弃用的.NET Remoting服务器激活对象,让MyProp作为远程代理而非序列化对象传输。以下是WCF和gRPC的具体实现方案:
方案一:WCF实现远程对象代理
WCF默认会序列化数据契约对象,要实现远程代理,需将Class1和Class2都定义为服务契约,通过返回服务接口来生成透明代理。
1. 定义服务契约
using System.ServiceModel; using System.IO; using System.Text; // Class1的服务契约,暴露获取Class2代理的方法 [ServiceContract] public interface IClass1 { [OperationContract] IClass2 GetMyProp(); } // Class2的服务契约,暴露远程调用的方法 [ServiceContract] public interface IClass2 { [OperationContract] string GetText(); }
2. 实现服务类
// 服务器激活的单例实例(对应Remoting的Singleton SAO) [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class Class1 : IClass1 { private readonly IClass2 _myProp; public Class1() { _myProp = new Class2(); } // 返回Class2的服务实例,WCF会自动生成远程代理 public IClass2 GetMyProp() { return _myProp; } } public class Class2 : IClass2 { public string GetText() { return File.ReadAllText(@"c:\file.txt", Encoding.UTF8); } }
3. 服务器端寄宿服务
using System.ServiceModel; var baseUri = new Uri("net.tcp://localhost:8080/"); using var host = new ServiceHost(typeof(Class1), baseUri); // 添加IClass1和IClass2的端点 host.AddServiceEndpoint(typeof(IClass1), new NetTcpBinding(), "Class1"); host.AddServiceEndpoint(typeof(IClass2), new NetTcpBinding(), "Class2"); host.Open(); Console.WriteLine("WCF服务已启动,按任意键停止..."); Console.ReadKey();
4. 客户端调用
using System.ServiceModel; // 创建Class1的代理 var class1Factory = new ChannelFactory<IClass1>( new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:8080/Class1") ); IClass1 class1Proxy = class1Factory.CreateChannel(); // 获取Class2的远程代理(而非序列化对象) IClass2 class2Proxy = class1Proxy.GetMyProp(); // 远程执行GetText,结果返回客户端 string result = class2Proxy.GetText(); Console.WriteLine(result);
方案二:gRPC模拟远程对象代理
gRPC基于消息传递,没有原生的透明代理,但可以通过将每个对象的方法封装为独立服务,模拟Remoting的远程调用行为。
1. 定义Proto文件
syntax = "proto3"; option csharp_namespace = "RemoteProxyGrpc"; // Class1对应的服务,用于获取Class2的访问入口 service Class1Service { rpc GetMyProp (EmptyRequest) returns (EmptyResponse); } // Class2对应的服务,暴露业务方法 service Class2Service { rpc GetText (EmptyRequest) returns (TextResponse); } message EmptyRequest {} message EmptyResponse {} message TextResponse { string text = 1; }
2. 生成并实现gRPC服务
using Grpc.Core; using System.IO; using System.Text; public class Class1ServiceImpl : Class1Service.Class1ServiceBase { public override Task<EmptyResponse> GetMyProp(EmptyRequest request, ServerCallContext context) { // 这里无需返回额外信息,客户端直接访问Class2Service即可 return Task.FromResult(new EmptyResponse()); } } public class Class2ServiceImpl : Class2Service.Class2ServiceBase { public override Task<TextResponse> GetText(EmptyRequest request, ServerCallContext context) { string text = File.ReadAllText(@"c:\file.txt", Encoding.UTF8); return Task.FromResult(new TextResponse { Text = text }); } }
3. 服务器端启动服务
using Grpc.Core; var server = new Server { Services = { Class1Service.BindService(new Class1ServiceImpl()), Class2Service.BindService(new Class2ServiceImpl()) }, Ports = { new ServerPort("localhost", 5001, ServerCredentials.Insecure) } }; server.Start(); Console.WriteLine("gRPC服务已启动,按任意键停止..."); Console.ReadKey(); server.ShutdownAsync().Wait();
4. 客户端调用
using Grpc.Net.Client; // 创建Class1客户端(验证服务可用性,或获取Class2的访问信息) var channel = GrpcChannel.ForAddress("http://localhost:5001"); var class1Client = new Class1Service.Class1ServiceClient(channel); class1Client.GetMyProp(new EmptyRequest()); // 创建Class2客户端,直接远程调用方法 var class2Client = new Class2Service.Class2ServiceClient(channel); var response = class2Client.GetText(new EmptyRequest()); Console.WriteLine(response.Text);
关键说明
- WCF的方案更接近Remoting的透明代理体验,客户端拿到的
IClass2是真正的远程代理,所有方法调用都会转发到服务器执行。 - gRPC更适合分布式服务场景,需要将每个对象的方法拆分为独立的gRPC服务,客户端通过服务客户端实现远程调用。
内容的提问来源于stack exchange,提问作者Saftpresse99
相关产品推荐
相关产品推荐

