3

私は最近、 AspBoilerplate (Abp) を使用して新しいプロジェクトを開始し、SignalR をある種のブロードキャスト メカニズムとして使用して、データベース内のレコードが変更されたか、追加または削除されたかを接続クライアントに通知しました。SignalR Hub を AppService へのプロキシとして使用すると、すべて正常に動作し、クライアントに通知されます

public class TestHub : Hub
{
    IMyAppService = _service
    public TestHub(IMyAppService service)
    {
        _service = service;
    }

    public void CreateEntry(EntryDto entry)
    {
        _service.Create(entry);
        Clients.All.entryCreated(entry);
    }
}

しかし、Abpの EventBus の利点を活用しようとすると、AppSevice を実装してイベントを EventBus に送信します。

class MyAppService : ApplicationService, IMyAppService 
{
    public IEventBus EventBus { get; set; }

    private readonly IMyRepository _myRepository;


    public LicenseAppService(ILicenseRepository myRepository)
    {
        EventBus = NullEventBus.Instance;
        _myRepository = myRepository;
    }

    public virtual EntryDto CreateLicense(EntryDto input)
    {            
        var newEntry = Mapper.Map<EntryDto >(_myRepository.Insert(input));

        EventBus.Trigger(new EntryCreatedEventData { Entry = newEntry});
        return newEntry;
    }
}

次に、ハブを EventHandler として直接使用しようとしましたが、イベントを処理する必要があるたびに abp が EventHandler クラスの独自のインスタンスを作成するため、これは失敗しました。ただし、完全を期すためのコードは次のとおりです。

public  class TestHub : Hub,
    IEventHandler<EntryCreatedEventData>
{ 
      public void Handle(EntryCreatedEventData data)
      {
           Clients.All.entryCreated(data.Entry);
      }
}

この後、別のリスナークラスを作成し、このようなハブコンテキストを使用して、かなり空のハブを使用しようとしました:

public  class TestHub : Hub
{ 
}

public  class EntryChangeEventHandler : IEventHandler<EntryCreatedEventData>
{ 
      private IHubContext _hubContext;
      public EntryChangeEventHandler()
      {
        _hubContext = GlobalHost.ConnectionManager.GetHubContext<TestHub>();

      public void Handle(EntryCreatedEventData data)
      {
        _hubContext.Clients.All.entryCreated(eventData.Entry);
      }
}

最後のソリューションでは、すべてがラインまで実行されます

_hubContext.Clients.All.entryCreated(eventData.Entry);

しかし、私のjavascript実装のクライアント側では、メソッドが呼び出されることはありません。クライアント側 (DurandalJs に基づく) は、ハブをプロキシとして使用することと、私が望む新しい方法の間で変わりませんでした。

シグナルを操作するためのクライアント側プラグイン

define(["jquery", "signalr.hubs"],
function ($) {
    var myHubProxy


    function connect(onStarted, onCreated, onEdited, onDeleted) {

        var connection = $.hubConnection();
        myHubProxy = connection.createHubProxy('TestHub');

        connection.connectionSlow(function () {
            console.log('We are currently experiencing difficulties with the connection.')
        });
        connection.stateChanged(function (data) {
            console.log('connectionStateChanged from ' + data.oldState + ' to ' + data.newState);
        });

        connection.error(function (error) {
            console.log('SignalR error: ' + error)
        });

        myHubProxy .on('entryCreated', onCreated);
        myHubProxy .on('updated', onEdited);
        myHubProxy .on('deleted', onDeleted);
        connection.logging = true;
        //start the connection and bind functions to send messages to the hub
        connection.start()
            .done(function () { onStarted(); })
            .fail(function (error) { console.log('Could not Connect! ' + error); });
    }    

    return signalr =
        {
            connect: connect
        };
});

プラグインを使用して表示:

define(['jquery', 'signalr/myHub],
    function ($, myHubSR) {
        return function () {
            var that = this;
            var _$view = null;

            that.attached = function (view, parent) {
                _$view = $(view);
            }

            that.activate = function () {
                myHubSR.connect(that.onStarted, that.onCreated, that.onEdited, that.onDeleted);
            }

            that.onStarted= function () { 
                //do something 
            }
            that.onCreated= function (data) { 
                //do something
            }
            that.onEdited = function (data) { 
                //do something
            }
            that.onDeleted= function (data) {
                //do something 
            } 
       }       
});       

したがって、私が呼び出したときに onCreated が呼び出されない理由は誰にも分かります

_hubContext.Clients.All.entryCreated(eventData.Entry);

?

signalR 通信がまったく機能するかどうかをテストするために、クライアント メソッドを直接呼び出すメソッドを追加しました。このメソッドを呼び出すと、更新がクライアントに正常にプッシュされます。問題は、IHubContextを使用するすべてのクライアントへのリモート呼び出しにあると思います.IHubContextの使用で何がうまくいかないかの手がかりはありますか?

public class TestHub : Hub
{
    public TestHub ()
        :base()
    { }

    public void Test()
    {
        this.Clients.All.entryCreated(new EntryDto());
    }
}
4

2 に答える 2

4

まず、EntryChangeEventHandler を DI に登録しましたか? そうでない場合は、EntryChangeEventHandler の ITransientDependency インターフェイスも実装します。

問題はシリアル化に関連している可能性があります。eventData.Entry をシリアライズしない場合があります。別の DTO オブジェクトの送信を試みることができます。

また、実装することができます

IEventHandler<EntityChangedEventData<Project>>

Project エンティティのすべての変更 (挿入、更新、削除を含む) をリッスンするため。プロジェクトは、ここでは単なるサンプル エンティティです。

最初のケースでは、DI に登録されていない場合、TestHub は機能しません。TestHub クラスの ITransientDependency も実装できます。また、DI コンテナーから取得するには、SignalR を作成する必要があります。そのようなクラスを使用できます:

public class WindsorDependencyResolver : DefaultDependencyResolver
{
    public override object GetService(Type serviceType)
    {
        return IocManager.Instance.IocContainer.Kernel.HasComponent(serviceType) ? IocManager.Instance.IocContainer.Resolve(serviceType) : base.GetService(serviceType);
    }

    public override IEnumerable<object> GetServices(Type serviceType)
    {
        return IocManager.Instance.IocContainer.Kernel.HasComponent(serviceType) ? IocManager.Instance.IocContainer.ResolveAll(serviceType).Cast<object>() : base.GetServices(serviceType);
    }
}

そして、起動時に設定します:

GlobalHost.DependencyResolver = new WindsorDependencyResolver();

たぶん私の答えは少し混乱していました:)理解していただければ幸いです。

于 2015-07-08T16:22:05.790 に答える