首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在SignalR中传递具有适当套管的复杂对象?

如何在SignalR中传递具有适当套管的复杂对象?
EN

Stack Overflow用户
提问于 2015-11-14 21:26:27
回答 3查看 492关注 0票数 2

在我的c#中有这样一个复杂的类:

代码语言:javascript
复制
public class Channel
{
    public int Id { get; set; }
    public string ChannelName { get; set; }
    public Dictionary<int, Question> Questions { get; set; }
    public Dictionary<int, ChatMessage> ChatMessages { get; set; }
    public Dictionary<int, User> Users { get; set; }
    public bool IsAdmin { get; set; }
    public int TimeLeft { get; set; }
}

要将它传递给我的客户,我需要:Clients.Caller.CheckVersion(ChannelInstance);

我的问题是,当我在客户机上收到对象时,它仍然拥有CamelCasing,而不是camelCasing。有任何方法可以做到这一点,因此SignalR将自动将我的对象转换为一个具有适当变量大小写的对象吗?

我知道这是一件很琐碎的事情,但我发现在我的javascript中定义这样一个类是很烦人的:

代码语言:javascript
复制
function Channel() {
    this.Id;
    this.ChannelName;
    this.etc;
}

当这看起来更符合JavaScript时:

代码语言:javascript
复制
function Channel() {
    this.id;
    this.channelName;
    this.etc;
}

有什么办法可以做到这一点吗?还是我只需要用奇怪的CamelCasing来解决?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-11-16 01:12:34

正如Rob在这个答案中声明的那样,显然不可能在不破坏SignalR的情况下更改全局JsonSerializerSettings。快速对源的搜索显示,它有时执行new JsonSerializer(),有时执行JsonSerializer.CreateDefault(),这可能导致至少部分问题。

话虽如此,您可能会采用从问题SignalR图形处理到您的需要的技巧,特别是覆盖Json.NET的行为,并且只对标记有特定属性的类型或在带有特定属性的程序集中使用camel大小写,使用以下合同解析器

代码语言:javascript
复制
public sealed class ConditionalCamelCaseContractResolver : IContractResolver
{
    readonly static IContractResolver defaultContractResolver;
    readonly static IContractResolver camelCaseContractResolver;
    readonly static ConcurrentDictionary<Type, bool> camelCaseTable;
    static Func<Type, bool> isCamelCase;

    // Use a static constructor for lazy initialization.
    static ConditionalCamelCaseContractResolver()
    {
        defaultContractResolver = new JsonSerializer().ContractResolver; // This seems to be the only way to access the global singleton default contract resolver.
        camelCaseContractResolver = new CamelCasePropertyNamesContractResolver();
        camelCaseTable = new ConcurrentDictionary<Type, bool>();
        isCamelCase = (t) => GetIsCamelCase(t);
    }

    static bool GetIsCamelCase(Type objectType)
    {
        if (objectType.Assembly.GetCustomAttributes<JsonCamelCaseAttribute>().Any())
            return true;
        if (objectType.GetCustomAttributes<JsonCamelCaseAttribute>(true).Any())
            return true;
        foreach (var type in objectType.GetInterfaces())
            if (type.GetCustomAttributes<JsonCamelCaseAttribute>(true).Any())
                return true;
        return false;
    }

    static bool IsCamelCase(Type objectType)
    {
        var code = Type.GetTypeCode(objectType);
        if (code != TypeCode.Object && code != TypeCode.Empty)
            return false;
        return camelCaseTable.GetOrAdd(objectType, isCamelCase);
    }

    #region IContractResolver Members

    public JsonContract ResolveContract(Type type)
    {
        return IsCamelCase(type) ? camelCaseContractResolver.ResolveContract(type) : defaultContractResolver.ResolveContract(type);
    }

    #endregion
}

[System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Interface)]
public class JsonCamelCaseAttribute : System.Attribute
{
    public JsonCamelCaseAttribute()
    {
    }
}

接下来,使用此属性标记程序集、类型或接口,以启用骆驼大小写:

代码语言:javascript
复制
[assembly: MyNamespace.JsonCamelCaseAttribute]

最后,使用那个问题中所示的技术,使用以下设置安装契约解析器:

代码语言:javascript
复制
public static class ConverterSettings
{
    public static JsonSerializer GetSerializer()
    {
        return JsonSerializer.Create(new JsonSerializerSettings()
        {
            ContractResolver = new ConditionalCamelCaseContractResolver()
        });
    }
}

由于SignalR自己的内部类型不会被如此标记,它们将继续使用默认设置进行序列化。

注:使用各种测试用例进行测试,但不使用SignalR本身,因为我目前还没有安装它。

票数 1
EN

Stack Overflow用户

发布于 2015-11-15 20:34:02

不,当您更改服务器上的默认JSON.net序列化设置时,通过使用JsonSerializerSettings类,SignalR jquery客户端将停止工作,因为它希望使用默认的JSON.net序列化设置来序列化服务器消息。我相信第三版他们会改变这一点的。

票数 1
EN

Stack Overflow用户

发布于 2021-05-15 16:25:09

我知道这是个老生常谈的问题,但这个快速的解决方案可能会帮助人们解决这个问题。在过去,它确实对我有帮助。

DataContractDataMember属性可能正是您想要以您想要的方式序列化类的对象,并且仍然保留大写字母C#。

你的课会是这样的:

代码语言:javascript
复制
[DataContract]
public class Channel
{
    [DataMember(Name = "id")]
    public int Id { get; set; }
    [DataMember(Name = "channelName")]
    public string ChannelName { get; set; }
    [DataMember(Name = "questions")]
    public Dictionary<int, Question> Questions { get; set; }
    
    ...
}

这将按您想要的方式序列化它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33713565

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档