0

我正在使用 SignalR 2.2.2(最新版本)和 .NET 4.5.2

我有这个错误:

无法创建 DF.ApplicationBlocks.IPropertyValueData 类型的实例。类型是接口或抽象类,不能实例化。路径“Properties[0].Id”,第 1 行,位置 881。

问题是 :

我有一个发送自定义对象的 SignalR 客户端(用 .NET 编写,使用 Signal.Client 包),在此对象上有一个对象数组,类型为接口(IPropertyValueData)。数组中的值是此接口的实现。

在 signalR 客户端中,我已配置为使用 TypeNameHandling.Auto :

        this._connection.JsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
        this._connection.JsonSerializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
        this._connection.JsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;

它正确地做到了,因为这是客户端发送的内容的摘录:

"Properties":[  
    {  
       "$id":"20",
       "$type":"DF.MailFlow.Services.Contract.Data.MailDataProperty, DF.MailFlow.Services.Contract",
       "Id":"5588ce9e-30fb-45b1-afbe-1e6ad0c3e8d4",

所以定义了 $type 属性并且值是正确的。但是无论如何,服务器在收到消息时仍然会触发错误。

我还将服务器配置为使用 TypeNameHandling.Auto,这是集线器的配置方式(我使用 Castle Windsor 作为 IoC):

        var resolver = new WindsorDependencyResolver(WebAPILoader.Container);

        var hubConfig = new HubConfiguration()
        {
            EnableJSONP = true,
            EnableDetailedErrors = true,
            EnableJavaScriptProxies = true,
            Resolver = resolver
        };


        GlobalHost.DependencyResolver = resolver;

        // Configure signalR and run it
        app.UseCors(CorsOptions.AllowAll);
        app.Map("/live", map =>
        {
            map.UseCors(CorsOptions.AllowAll);
            map.RunSignalR(hubConfig);
        });

        var serializerSettings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Auto,
            PreserveReferencesHandling = PreserveReferencesHandling.Objects,
            ReferenceLoopHandling = ReferenceLoopHandling.Serialize
        };
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = serializerSettings;
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;

        // Register in Castle.Windsor container
        WebAPILoader.Container.Register(Castle.MicroKernel.Registration.Component
                              .For<JsonSerializer>()
                              .UsingFactoryMethod(() => JsonSerializer.Create(serializerSettings)));

我检查了当收到第一条消息时,工厂方法被调用并且设置仍然具有正确的 TypeNameHandling.Auto。

我还测试了以这种方式注册序列化程序:

GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => JsonSerializer.Create(serializerSettings));

但是没办法,服务器在收到消息时总是会触发同样的错误。

更复杂的是,应用程序同时运行 signalr 和 webapi 组件(在不同的 url 中)。我已经检查过 webapi 没有注册任何 JsonSerializer,并且使用的 Windsor 容器对于两个组件都是相同的。

任何想法 ?

编辑#1:

我刚刚在这张票上跑了https://github.com/SignalR/SignalR/issues/3304
似乎令人难以置信的是,即使有人做了 PR(https:// github.com/SignalR/SignalR/pull/3343
所以现在我正在尝试找到一种解决方法......

4

1 回答 1

0

这个问题显然是由于 SignalR 中的错​​误

链接中发布的解决方法有效,即注册自定义解析器:

private class Resolver : DefaultParameterResolver
{
    private readonly JsonSerializer _serializer;

    public Resolver(JsonSerializer serializer)
    {
        _serializer = serializer;
    }

    private FieldInfo _valueField;
    public override object ResolveParameter(ParameterDescriptor descriptor, Microsoft.AspNet.SignalR.Json.IJsonValue value)
    {
        if (value.GetType() == descriptor.ParameterType)
        {
            return value;
        }

        if (_valueField == null)
            _valueField = value.GetType().GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic);

        var json = (string)_valueField.GetValue(value);
        using (var reader = new StringReader(json))
            return _serializer.Deserialize(reader, descriptor.ParameterType);
    }
}

关于如何解决这个错误的讨论现在在这张票上,所以当它(希望)得到解决时你可以在那里找到

于 2017-11-09T18:42:44.100 回答