从不同的 AppDomain 调用 SignalR 方法 [英] Call a SignalR method from a different AppDomain

查看:24
本文介绍了从不同的 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.

现在我必须在不同的 AppDomains 中重新定位我的控制器.这打破了 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).

我发现了很多关于从控制器/其他类/任何东西调用 SignalR 集线器方法的示例/问题/教程,但没有来自默认应用程序域(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 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆