从其他AppDomain调用SignalR方法

从其他AppDomain调用SignalR方法

本文介绍了从其他AppDomain调用SignalR方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用SignalR用C#编写的可工作的Web服务器.这是一个自托管的Owin应用程序.一切正常.

I have a working web server written in C# using SignalR. It's a self-hosted Owin Application. Everything works fine.

现在,我必须将控制器重新放置在不同的AppDomain中.这破坏了SignalR部分,因为GlobalHost仅在一个AppDomain中保持不变,并且不可序列化(因此,我无法将其直接传递给其他AppDomain).

Now I have to relocate my controllers in different AppDomains. This breaks the SignalR part, because GlobalHost remains the same only within one AppDomain, and is not serializable (thus I can't pass it along to other AppDomains as it is).

我已经找到了许多关于从Controller/其他类/类调用SignalR集线器方法的示例/问题/教程,但没有从Default AppDomain(用于初始化Owin应用程序的外部)之外的任何内容.

I've found a lot of examples/questions/tutorials about calling SignalR hubs methods from a Controller/an other class/whatever, but nothing from outside the Default AppDomain (the one where the Owin application is initialized).

如何从与集线器不同的AppDomain中设置的控制器向客户端发送消息?

How can I send a message to a client from a controller set in a different AppDomain than the Hub ?

推荐答案

我发现的解决方案非常简单:至于AppDomain之间的任何通信,我们都需要能够跨越AppDomain边界的东西,因此数据或代理上课.

The solution I found is pretty simple: as for any inter-AppDomain communication, we need something that can cross the boundaries of an AppDomain, thus data or a proxy to a class.

因此,以下作品:

  1. 创建一个扩展MarshalByRefObject的类:当我们将该类传递给另一个AppDomain中的另一个类时,它将自动创建该类的代理

  1. Create a class extending MarshalByRefObject: this will automatically create a proxy to this class when we pass it to a other class in a different AppDomain

public class InterAppDomainForSignalR : MarshalByRefObject
{
    public void Publish(PublishParameter param) {
        var clients = GlobalHost.ConnectionManager.GetHubContext<TradeHub>().Clients;
        dynamic chan;
        if (param.group != null && param.group.Length > 0)
        {
            chan = clients.Group(param.group, param.ids);
        }
        else
        {
            if(param.ids == null || param.ids.length = 0) {
                return; //not supposed to happen
            }
            chan = clients.Client(param.ids[0]);
        }
        chan.OnEvent(param.channelEvent.ChannelName, param.channelEvent);
    }
}

[Serializable]
public class PublishParameter
{
    public string group { get; set; }
    public string[] ids { get; set; }
    public ChannelEvent channelEvent { get; set; }
}

确保您的参数为Serializable:在这里,PublishParameter显然是正确的,但是ChannelEvent也必须可序列化,并且仅包含Serializable成员,等等...

Make sure your parameters are Serializable: here, PublishParameter is obviously correct, BUT ChannelEvent has to be serializable too, and contain only Serializable members, etc...

  1. 创建此类的实例,并将其传递给不同AppDomains中的对象(communicationChannelInterAppDomainForSignalR的实例):

AppDomain domain = AppDomain.CreateDomain(myDomainName);

Type type = typeof(ClassInOtherAppDomain);
ClassInOtherAppDomain startpoint = (ClassInOtherAppDomain)domain.CreateInstanceAndUnwrap(
        type.Assembly.FullName,
        type.FullName) as ClassInOtherAppDomain;

var session = startpoint.initialize(communicationChannel);

  • communicationChannel存储在ClassInOtherAppDomain实例中,并随意使用;):

  • Store the communicationChannel in the ClassInOtherAppDomain instance, and use it at will ;) :

    public class ClassInOtherAppDomain {
        private InterAppDomainForSignalR communicationChannel { get; set; }
    
        public void initialize(InterAppDomainForSignalR communicationChannel) {
            this.communicationChannel = communicationChannel;
        }
    
        public void Publish(PublishParameter param) {
            this.communicationChannel.Publish(param);
        }
    }
    

  • 就这样=)

    有关如何实现AppDomain之间通信的更多文档,请参见 此处.

    More documentation on how to implement inter-AppDomain communication can be found here and here.

    这篇关于从其他AppDomain调用SignalR方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-28 02:24