简体   繁体   English

在.NET远程处理RemotingConfiguration.RegisterWellKnownServiceType和RemotingServices.Marshal之间有什么区别?

[英]In .NET remoting what is the difference between RemotingConfiguration.RegisterWellKnownServiceType and RemotingServices.Marshal?

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);

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. RegisterWellKnownServiceType将创建该对象并使其成为使用它的任何客户端的Singleton,但不会创建服务器的引用。 The object is not created until a client ask for it, and the same object is used for any other clients. 在客户端请求对象之前不会创建该对象,并且该对象将用于任何其他客户端。

RemotingServices.Marshal(foo);

Marshal will register an object that has been created by the server, in this case a windows service. Marshal将注册一个由服务器创建的对象,在本例中是一个Windows服务。 Then server will then have reference to the object and the clients will consume the same object. 然后,服务器将引用该对象,并且客户端将使用相同的对象。

My issue was using the Marshal to register the remoting object. 我的问题是使用Marshal注册远程对象。 Over time the remoting object will disappear for clients to consume, ie 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. 然后我尝试了RegisterWellKnownServiceType并且客户端不断获得正确的引用,但是我无法让服务获得对同一对象的引用。

The solution is overriding the remoting object in this case FooRemoting. 在这种情况下,解决方案是覆盖远程处理对象FooRemoting。 If I overrode the InitializeLifetimeService and returned null, the client would never lose connection, and the service will, keep the connection. 如果我覆盖了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。

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. 它有3个项目:服务器,客户端和核心。 Server and Client both reference Core but do not reference each other. 服务器和客户端都引用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.rem which 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. 实例化可以由您自己的代码而不是.NET控制。 Very useful when dealing with constructor-based dependency injection with remoting objects. 在处理基于构造函数的依赖注入和远程处理对象时非常有用。

I did one experiment with RemotingServices.Marshal like this 我做了一个像RemotingServices.Marshal这样的实验

Remotable component hosted in a Windows Exe. 远程组件托管在Windows Exe中。 Exe code is 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次

  1. When the RemoteClass object is created in the Service itself 在服务本身中创建RemoteClass对象时
  2. When the client is making call to MyVal property. 当客户端调用MyVal属性时。

I think RemotingServices.Marshal has nothing to do with the single instance. 我认为RemotingServices.Marshal与单个实例无关。 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. 即使您只使用RemotingConfiguration.Configure并覆盖InitializeLifetimeService以使其返回null,也足以托管远程组件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何撤消RemotingConfiguration.RegisterWellKnownServiceType()? - How to undo RemotingConfiguration.RegisterWellKnownServiceType()? RemotingServices.Marshal(foo,uri)仅在短时间内工作。 如何保持运作? - RemotingServices.Marshal(foo, uri) only works for a short period of time. How to keep it working? .NET远程处理:RegisterWellKnownServiceType处的异常“值NULL” - .NET Remoting: Exception “Value NULL” at RegisterWellKnownServiceType .NET Remoting-有关RegisterWellKnownServiceType和激活远程对象的问题 - .NET Remoting - Question about RegisterWellKnownServiceType and activation of remote object Web服务和远程处理有什么区别? - What is the difference between web service and remoting? WebService和Remoting之间的区别 - Difference between WebService and Remoting .Net Remoting和用于XML编码和Http通信的Web服务之间的区别 - Difference between .Net Remoting and Web Service for XML encoding and Http Communication Marshal.SizeOf(typeof(T))和Marshal.SizeOf(default(T))之间有什么区别? - What's the difference between Marshal.SizeOf(typeof(T)) and Marshal.SizeOf(default(T))? MethodHandle.GetFunctionPointer和Marshal.GetFunctionPointerForDelegate有什么区别 - What's the difference between MethodHandle.GetFunctionPointer and Marshal.GetFunctionPointerForDelegate 重用.NET RemotingServices中的对象URI - Reuse an Object URI in .NET RemotingServices
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM