C# 在 .NET 远程处理中,RemotingConfiguration.RegisterWellKnownServiceType 和 RemotingServices.Marshal 之间有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/493455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In .NET remoting what is the difference between RemotingConfiguration.RegisterWellKnownServiceType and RemotingServices.Marshal?
提问by David Basarab
In .NET remoting what is the difference between RemotingConfiguration.RegisterWellKnownServiceType and RemotingServices.Marshal?
在 .NET 远程处理中,RemotingConfiguration.RegisterWellKnownServiceType 和 RemotingServices.Marshal 之间有什么区别?
What I want to do is create an object in a Windows Service, then put it in as a remoting object and have the Windows Service and the Client both act on the remoting object.
我想要做的是在 Windows 服务中创建一个对象,然后将其作为远程对象放入,并使 Windows 服务和客户端都作用于远程对象。
I thought the below code would accomplish this.
我认为下面的代码可以实现这一点。
FooRemoting foo = new FooRemoting();
RemotingConfiguration.RegisterWellKnownServiceType(typeof(FooRemoting), serverName, WellKnownObjectMode.Singleton);
RemotingServices.Marshal(foo);
采纳答案by David Basarab
This is what I found.
这是我发现的。
RemotingConfiguration.RegisterWellKnownServiceType(typeof(FooRemoting),
serverName, WellKnownObjectMode.Singleton);
RegisterWellKnownServiceType will create the object and make it a Singleton to any client that consumes it, but a reference by the server is not created. The object is not created until a client ask for it, and the same object is used for any other clients.
RegisterWellKnownServiceType 将创建该对象并使其成为任何使用它的客户端的单例,但不会创建服务器的引用。在客户端请求之前不会创建该对象,并且相同的对象用于任何其他客户端。
RemotingServices.Marshal(foo);
Marshal will register an object that has been created by the server, in this case a windows service. Then server will then have reference to the object and the clients will consume the same object.
Marshal 将注册一个由服务器创建的对象,在本例中为 Windows 服务。然后服务器将引用该对象,客户端将使用相同的对象。
My issue was using the Marshal to register the remoting object. Over time the remoting object will disappear for clients to consume, i.e. no longer on the remoting object. The service would still keep its reference. Then I tried the RegisterWellKnownServiceType and the clients keep getting the correct reference, however I could not get the service to have a reference to the same object.
我的问题是使用 Marshal 注册远程对象。随着时间的推移,远程对象将消失供客户端使用,即不再在远程对象上。该服务仍将保留其引用。然后我尝试了 RegisterWellKnownServiceType 并且客户端不断获得正确的引用,但是我无法让服务引用同一个对象。
The solution is overriding the remoting object in this case FooRemoting. If I overrode the InitializeLifetimeService and returned null, the client would never lose connection, and the service will, keep the connection.
在这种情况下,解决方案是覆盖远程处理对象 FooRemoting。如果我覆盖 InitializeLifetimeService 并返回 null,则客户端将永远不会丢失连接,并且服务将保持连接。
public override object InitializeLifetimeService()
{
//return base.InitializeLifetimeService();
return null;
}
In order to keep the object created by the service and have the client to use the same object you must use
为了保持服务创建的对象并让客户端使用相同的对象,您必须使用
RemotingServices.Marshal(foo);
and override InitializeLifetimeService to return null.
并覆盖 InitializeLifetimeService 以返回 null。
回答by David Basarab
I did one experiment with RemotingServices.Marshal like this
我像这样用 RemotingServices.Marshal 做了一个实验
Remotable component hosted in a Windows Exe. Exe code is
托管在 Windows Exe 中的远程组件。exe代码是
Form1_Load(object sender, EventArgs e)
{
RemotingConfiguration.Configure("path of the config file");
RemoteClass obj = new RemoteClass();
obj.MyVal =100;
RemotingServices.Marshal(obj);
}
public RemoteClass: MarshalByRefObj
{
static int Counter;
public RemoteClass()
{
Counter++;
}
int _MyVal =0;
public int MyVal
{
get
{
return _MyVal;
}
set
{
_MyVal = value;
}
}
}
Now in the client side code
现在在客户端代码中
button1_click()
{
RemoteClass obj = Activator.GetObject(typeof(RemoteClass), "object URI");
if(RemotingServices.IsTransparentProxy(obj))
{
MessageBox.Show(obj.Myval.ToString());
}
}
It will popup the message as 0 not 100. If you put a breakpoint in the constructor of RemoteClass, you will see that the constructor is getting called 2 times
它将弹出消息为 0 而不是 100。如果在 RemoteClass 的构造函数中放置断点,您将看到构造函数被调用了 2 次
- When the RemoteClass object is created in the Service itself
- When the client is making call to MyVal property.
- 当在服务本身中创建 RemoteClass 对象时
- 当客户端调用 MyVal 属性时。
I think RemotingServices.Marshal has nothing to do with the single instance. Even if you use just RemotingConfiguration.Configure and override the InitializeLifetimeService so that it will return null, will be sufficient to host a remotable component.
我认为 RemotingServices.Marshal 与单个实例无关。即使您只使用 RemotingConfiguration.Configure 并覆盖 InitializeLifetimeService 使其返回 null,也足以承载远程组件。
回答by Daniel Flower
It is possible to expose MarshalByRefObjects which have parameterful constructors over remoting, and it's possible for users of the class to only deal with its interface.
可以通过远程处理公开具有参数构造函数的 MarshalByRefObjects,并且类的用户可能只处理其接口。
I have created a small proof of concept project. It has 3 projects: Server, Client, and Core. Server and Client both reference Core but do not reference each other.
我创建了一个小型的概念验证项目。它有 3 个项目:服务器、客户端和核心。Server 和 Client 都引用 Core,但不相互引用。
In core, we define a service interface:
在核心中,我们定义了一个服务接口:
namespace Core
{
public interface ICountingService
{
int Increment();
}
}
The server defines the concrete implementation, which the client doesn't have a reference to:
服务器定义了具体的实现,客户端没有引用:
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;
}
}
}
The important bits to note are that it has a constructor with a parameter, it is a MarshalByRefObject, and it implements the interface in the core project.
需要注意的重要一点是它有一个带参数的构造函数,它是一个 MarshalByRefObject,它在核心项目中实现了接口。
The server project is a console app which sets up a remoting channel (arbitrarily over HTTP for this example), creates the service, and registers it with remoting:
服务器项目是一个控制台应用程序,它设置远程处理通道(在本示例中任意通过 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();
}
}
}
The above code has registered the URL http://localhost:8234/CountingService.remwhich holds the instantiated service, which will start counting from 5.
上面的代码已经注册了保存实例化服务的 URL http://localhost:8234/CountingService.rem,它将从 5 开始计数。
The client, also a console app, can then get a reference, using the interface class:
客户端,也是一个控制台应用程序,然后可以使用接口类获取引用:
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();
}
}
}
When the server and client are run, it prints values from 6 to 10.
当服务器和客户端运行时,它会打印 6 到 10 之间的值。
Summary: client knows only about the interface; implementation constructor can have parameters; instantiation can be controlled by your own code rather than by .NET. Very useful when dealing with constructor-based dependency injection with remoting objects.
总结:客户端只知道接口;实现构造函数可以有参数;实例化可以由您自己的代码而不是 .NET 控制。在处理远程对象的基于构造函数的依赖注入时非常有用。