可以通过远程处理公开具有参数构造函数的 MarshalByRefObjects,并且该类的用户可以仅处理其接口。
我创建了一个小型概念验证项目。它有 3 个项目:服务器、客户端和核心。服务器和客户端都引用Core,但不相互引用。
在核心中,我们定义了一个服务接口:
namespace Core
{
public interface ICountingService
{
int Increment();
}
}
服务器定义了具体的实现,客户端没有引用:
namespace Server
{
public class CountingService : MarshalByRefObject, ICountingService
{
private static int _value = 0;
public CountingService(int startValue)
{
_value = startValue;
}
public int Increment()
{ // not threadsafe!
_value++;
return _value;
}
}
}
需要注意的重要一点是它有一个带参数的构造函数,它是一个 MarshalByRefObject,它实现了核心项目中的接口。
服务器项目是一个控制台应用程序,它设置一个远程处理通道(在本示例中任意通过 HTTP),创建服务,并将其注册到远程处理:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
namespace Server
{
class Program
{
static void Main(string[] args)
{
HttpServerChannel serverChannel = new HttpServerChannel(8234);
ChannelServices.RegisterChannel(serverChannel, false);
// Following line won't work at runtime as there is no parameterless constructor
//RemotingConfiguration.RegisterWellKnownServiceType(typeof(CountingService),
// "CountingService.rem", WellKnownObjectMode.Singleton);
CountingService countingService = new CountingService(5);
RemotingServices.Marshal(countingService, "CountingService.rem");
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
}
}
上面的代码已经注册了 URL http://localhost:8234/CountingService.rem,其中保存了实例化的服务,将从 5 开始计数。
客户端,也是一个控制台应用程序,然后可以使用接口类获取引用:
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using Core;
namespace Client
{
class Program
{
static void Main(string[] args)
{
HttpClientChannel serverChannel = new HttpClientChannel();
ChannelServices.RegisterChannel(serverChannel, false);
for (int i = 0; i < 5; i++)
{
ICountingService countingService =
(ICountingService)Activator.GetObject(typeof(ICountingService),
"http://localhost:8234/CountingService.rem");
int newValue = countingService.Increment();
Console.WriteLine("Value is " + newValue);
}
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
}
}
当服务器和客户端运行时,它会打印从 6 到 10 的值。
总结:客户端只知道接口;实现构造函数可以有参数;实例化可以由您自己的代码而不是由 .NET 控制。在使用远程对象处理基于构造函数的依赖注入时非常有用。