.NET Client - AndersMalmgren/SignalR.EventAggregatorProxy GitHub Wiki
The .NET client have seen alot of breaking changes and improvements with Dot Net Core
Install the Core client using (Its netstandard 2.0 so works with Framework 4.x too). remark: Core 3.0 version uses netstandard 2.1 which is not working with full framework
Install-Package SignalR.EventAggregatorProxy.Client.DotNetCore
The .NET client has a built in event aggregator that you can use. We have also improved the pipeline for configuring it.
serviceProvider = new ServiceCollection()
.AddSignalREventAggregator()
.WithHubUrl("http://localhost:60976/EventAggregatorProxyHub")
.OnConnectionError(e => Debug.WriteLine(e.Message))
.Build()
There are some callback methods that you can call to listen to specific protocol state changes.
serviceProvider = new ServiceCollection()
.AddSignalREventAggregator()
.WithHubUrl("http://localhost:60976/EventAggregatorProxyHub")
.OnConnectionError(...)
.OnSubscriptionError(...)
.OnConnected(...)
.Build()
We no longer use a Base event to find out which events are proxied. Instead implement IEventTypefinder
and register it with the DI.
serviceProvider = new ServiceCollection()
.AddSignalREventAggregator()
.WithHubUrl("http://localhost:60976/EventAggregatorProxyHub")
.Build()
.AddSingleton<IEventTypeFinder, EventTypeFinder>()
Both your backend and client should share the same Assembly containing the events. This way you ensure that the fully qualified name is same in both cases.
AddSignalREventAggregator
Hooks up the dependency to the IProxyEventAggregator
There is also a version of it with client side only methods. Make sure they point to the same reference, the Dot Net Core DI does not support this out of the box, you can do
serviceProvider = new ServiceCollection()
.AddSignalREventAggregator()
.WithHubUrl("http://localhost:60976/EventAggregatorProxyHub")
.Build()
.AddSingleton<IEventAggregator>(p => p.GetService<IProxyEventAggregator>())
The event aggregator injected by AddSignalREventAggregator
is configured like a singleton. But you can also subscribe and publish client side only events. If you use the global singleton event aggregator all Models, services etc in the Application will receive the event. This is not always desired you can then register a Child IoC on a Window level or other level of your choice. If you do this make sure you register the IEventAggregator
interface for the local scope, otherwise they will conflict. You can then use IProxyEventAggregator
for global scope and IEventAggregator
for local scope.
The class that is a listener to a event must implement IHandle and also call subscribe on the Event aggregator like.
public class MyViewModel : IHandle<MyEvent>
{
public MyViewModel(IEventAggregator eventAggregator)
{
eventAggregator.Subscribe(this);
}
public void Handle(MyEvent message)
{
//Act on MyEvent
}
}
You can have multiple IHandle<> interfaces on a class.
As covered Here you can have constraints so that a client only receives a selection of a event. To hook up a constraint you have to change the subscription part a bit.
public MyViewModel(IProxyEventAggregator eventAggregator)
{
eventAggregator.Subscribe(this, builder => builder.For<MyEvent>().Add(new MyEventConstraint{ Id = 100 }));
}
This overload of Subscribe is only available on the IProxyEventAggregator
You can publish client side only events like
eventAggregator.Publish(new ClientSideEvent());
Maybe you have a existing event aggregator in your client, if this is the case you need to proxy between our SignalR proxy and your event aggregator. Use the EventProxy class for this. To see how it works check out the Source here at github.
Install the .NET client using
Install-Package SignalR.EventAggregatorProxy.Client.DotNet
Latest version of client requires SignalR.EventAggregatorProxy.1.4.117 or later
The .NET client has a built in event aggregator that you can use.
eventAggregator = new EventAggregator<EventBase>()
.Init("http://localhost");
The generic argument is the base class for all your events, both your backend and client should share the same Assembly containing the events. This way you ensure that the fully qualified name is same in both cases.
We choose to have a empty constructor for the EventAggregator because that way you can dependency inject the event aggregator. Instead you call Init on the instance to setup the URL for the hub. The init method also takes a delegate where you can add additional settings to the connection. For example to configure Windows authentication. Only call Init once.
eventAggregator = new EventAggregator<EventBase>()
.Init("http://localhost", c => c.Credentials = CredentialCache.DefaultCredentials);
There are some callback methods that you can call to listen to specific protocol state changes.
eventAggregator = new EventAggregator<EventBase>()
.OnConnected(() => Console.WriteLine("Connected"))
.OnConnectionError(e => Console.WriteLine(e.Message))
.OnSubscriptionError((e, s) => Console.WriteLine(e.Message))
.Init("http://localhost");
The best way of ensuring that the aggregator is just instanced once is to use a IoC and configure its lifetime management to be Singleton. With Ninject it would look like this.
kernel.Bind<IEventAggregator<BaseEvent>>().To<EventAggregator<BaseEvent>>().InSingletonScope();
You can also register it without the generic interface like
kernel.Bind<IEventAggregator>().To<EventAggregator<BaseEvent>>().InSingletonScope();
The event aggregator containing the hub proxy should always be configured like a singleton. But you can also subscribe and publish client side only events. If you use the global singleton event aggregator all Models, services etc in the Application will receive the event. This is not always desired you can then register a Child IoC on a Window level or other level of your choice. If you do this make sure you register the generic interface for the global scope. And the none generic interface for the local scope, otherwise they will conflict.
The class that is a listener to a event must implement IHandle and also call subscribe on the Event aggregator like.
public class MyViewModel : IHandle<MyEvent>
{
public MyViewModel(IEventAggregator eventAggregator)
{
eventAggregator.Subscribe(this);
}
public void Handle(MyEvent message)
{
//Act on MyEvent
}
}
You can have multiple IHandle<> interfaces on a class.
As covered Here you can have constraints so that a client only receives a selection of a event. To hook up a constraint you have to change the subscription part a bit.
public MyViewModel(IEventAggregator<EventBase> eventAggregator)
{
eventAggregator.Subscribe(this, new[] { new ConstraintInfo<MyEvent, MyEventConstraint>{ Id = 100 } });
}
This overload of Subscribe is only available on the generic version of the IEventAggregator
You can publish client side only events like
eventAggregator.Publish(new ClientSideEvent());
Maybe you have a existing event aggregator in your client, if this is the case you need to proxy between our SignalR proxy and your event aggregator. Use the EventProxy class for this. To see how it works check out the Source here at github.