4

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

Mario Toffia
  • 510
  • 5
  • 16
  • Am I understanding it correctly that you are putting objects of different types into SignalREvent.EventArguments on the server, and you're expecting that the serialized JSON will include some type information such that on the client the instances will be deserialized to those types? – Damian Edwards Sep 26 '12 at 18:57
  • Yes It does - I have updated the question with my ouput for the serialized data using this.hubConnection.Received += Console.WriteLine; // Mario – Mario Toffia Sep 26 '12 at 19:56
  • apparently, if you wrap your object types in an array, and then perform the deserialization of the array elements yourself, you can get back the object types! I have spent a day trying to figure this out and i think what is happening is that signalr is deserializing the single object and throwing out the type data but it doesn't deserialize an array, so you have the raw JSON from the server which you can do what you want with – Joe Nov 28 '12 at 02:12

1 Answers1

3

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 or Newtonsoft.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 to return obj.ToObject<T>(yourJsonSerializer).

halter73
  • 15,059
  • 3
  • 49
  • 60
  • Thanks for the response! Yes I can see it now (from git) - would you consider to have a custom serializer depending on the hub itself. I've currently plan to use around 6 - 8 hubs with different "services" and events. Some are meant to be used from websites and some are meant to be consumed / invoked by .net code. I actually just want to use different configurations (right now - switch to bson for .net - .net is attractive though ;) depending on .net <-> .net or .net vs "everything". Tanks again! – Mario Toffia Sep 30 '12 at 21:14