I'm new to SignalR and have done a simple test hack. I wish to serialize an object array with typed objects. By default SignalR has configured the JSon.NET serializer to not provide with type information. And I found that I could register a custom serializer in the DependencyResolver by:
var serializer =
new EventHubJsonSerializer(
new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
TypeNameHandling = TypeNameHandling.Objects
});
GlobalHost.DependencyResolver.Register(typeof(IJsonSerializer), () => serializer);
However when I recieve my object array it will not resolve the types, instead it is a JSonContainer. Can I solve this in any way?
The event emitted from the Hub:
public sealed class SignalREvent
{
public string Group { get; set; }
public string EventName { get; set; }
public string TypeFullName { get; set; }
public IList<object> EventArguments { get; set; }
}
And the receptor have to unwrap the boolean via casting to dynamic:
public sealed class TestEventArgs : EventArgs
{
#region Public Properties
/// <summary>
/// Gets or sets a value indicating whether do not print.
/// </summary>
public bool DoNotPrint { get; set; }
/// <summary>
/// Gets or sets the event name.
/// </summary>
public string EventName { get; set; }
#endregion
}
this.subscription = this.client.On<SignalREvent>(
"PushEvent",
data =>
{
dynamic eventArg1 = data.EventArguments[0];
if (eventArg1.DoNotPrint.Value)
{
return;
}
});
What I've done is a postsharp aspect to apply on events in order to allow them to propagate via SignalR via my EventHub. For example:
[ExternalizeEvent]
public event ASimpleDelegate SimpleEvent;
It's a darn simple aspect, but it would really be good to have type info when in the .net world - other clients would of course not benefit of this.
Update
This is the output for my JSon.NET configuration - types are propagated in the $type but it seems that it is not used during deseralization.
{
"$id": "11",
"$type": "<>f__AnonymousType0`3[[System.String, mscorlib],[System.String, mscorlib],[System.Object[], mscorlib]], SignalR",
"Hub": "Externalize.EventHub",
"Method": "PushEvent",
"Args": [
{
"$id": "12",
"$type": "DataDuctus.SignalR.Aspects.SignalREvent, DataDuctus.SignalR.Aspects",
"Group": "all",
"EventName": "SimpleEvent",
"TypeFullName": "TestConsole.TestEvents",
"EventArguments": [
{
"$id": "13",
"$type": "TestConsole.TestEventArgs, TestConsole",
"DoNotPrint": false,
"EventName": "second event (test)"
}
]
}
]
}
Cheers, Mario
The SignalR .NET client does not use the DependencyResolver from the server and currently does not have an IoC container of its own. Because of this, as you note in your question, your custom JsonSerializerSettings are used for serialization on the server but not for deserialization on the client.
In the next release of SignalR we plan to add a DependencyResolver to the .NET client that will allow you to provide your own
Newtonsoft.Json.JsonSerializer
orNewtonsoft.Json.JsonSerializerSettings
to be used during deserialization. There are currently no plans to allow the use of a non-Json.NET (de)serializer in the .NET client.If you need this functionality now, you could clone https://github.com/SignalR/SignalR.git and modify the
private static T Convert<T>(JToken obj)
method in SignalR.Client\Hubs\HubProxyExtensions.cs toreturn obj.ToObject<T>(yourJsonSerializer)
.