Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq to sql 选择性地将Linq2sql模型序列化为JSON_Linq To Sql_C# 4.0_Extension Methods_Json.net - Fatal编程技术网

Linq to sql 选择性地将Linq2sql模型序列化为JSON

Linq to sql 选择性地将Linq2sql模型序列化为JSON,linq-to-sql,c#-4.0,extension-methods,json.net,Linq To Sql,C# 4.0,Extension Methods,Json.net,我有来自mssql数据库的非常常见的linq2sql业务模型。表之间有一些关联,这很好。整个模型在单独的组件中。我正在使用JSON.NET库进行序列化 现在,我需要将这些模型序列化为JSON,并告诉它要使用哪些属性,现在使用哪些属性。使用if属性是不可能的,但我也不喜欢元数据类的想法 所以我一直在考虑以这种方式使用扩展方法: public static class User { public static object GetSerializable(this DataModel.User

我有来自mssql数据库的非常常见的linq2sql业务模型。表之间有一些关联,这很好。整个模型在单独的组件中。我正在使用JSON.NET库进行序列化

现在,我需要将这些模型序列化为JSON,并告诉它要使用哪些属性,现在使用哪些属性。使用if属性是不可能的,但我也不喜欢元数据类的想法

所以我一直在考虑以这种方式使用扩展方法:

public static class User {
  public static object GetSerializable(this DataModel.User user) {
    return new {
      user.Id, user.LoginName, user.FirstName, user.LastName
    }
  }
}
这将很好,但是我不确定在这种情况下如何使用它:

[JsonObject]
public class AuthModel {
  [JsonProperty]
  public DataModel.User { get; set; }
}
public abstract class SerializeSelectorConverter<TModel> : JsonConverter where TModel: class
{
    protected abstract object GetSerializableObject( TModel model );

    public override bool CanWrite { get { return true; } }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(TModel);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, GetSerializableObject( value as TModel ));
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
您知道如何有效地使用这些扩展方法吗?或者其他完全不同的想法?

您可以使用它将它们转换为json。此配置可以在代码中完成,而无需使用属性

选项2:您可以使用


选项3:您可以使用。将持久类转换为字典并使用它

好吧,我决定采用基于自定义JsonConverter的方法,其结果与上述方法非常相似。看起来是这样的:

[JsonObject]
public class AuthModel {
  [JsonProperty]
  public DataModel.User { get; set; }
}
public abstract class SerializeSelectorConverter<TModel> : JsonConverter where TModel: class
{
    protected abstract object GetSerializableObject( TModel model );

    public override bool CanWrite { get { return true; } }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(TModel);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, GetSerializableObject( value as TModel ));
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
公共抽象类序列化SelectorConverter:JsonConverter其中TModel:class
{
受保护的抽象对象GetSerializableObject(TModel模型);
公共覆盖布尔可写{get{return true;}}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(TModel);
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
serializer.Serialize(writer,GetSerializableObject(值为TModel));
}
公共重写bool CanRead{get{return false;}}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
抛出新的NotImplementedException();
}
}
然后我做了一个像这样的课程:

[JsonObject]
public class AuthModel {
    [JsonProperty]
    [JsonConverter(typeof(UserConverter))]
    public DataModel.User { get; set; }
}

private class UserConverter : SerializeSelectorConverter<DataModel.User>
{
    protected override object GetSerializableObject(DataModel.User model)
    {
        return new
        {
            model.Id,
            model.LoginName,
            model.FirstName,
            model.LastName
        };
    }
}
[JsonObject]
公共类身份验证模型{
[JsonProperty]
[JsonConverter(typeof(UserConverter))]
公共数据模型。用户{get;set;}
}
私有类UserConverter:SerializeSelectorConverter
{
受保护的覆盖对象GetSerializableObject(DataModel.User模型)
{
还新
{
model.Id,
model.LoginName,
model.FirstName,
model.LastName
};
}
}

非常简单,没有一些复杂的配置或元数据类。所有内容都经过编译器的正确验证,因此在发生更改时不会出现打字错误和问题。

我编写了一个自定义JsonConverter来处理这种情况,因为源类有一个接口枚举需要序列化的内容

您的类和序列化接口:

public interface IUser {
    Guid Id { get; set; }
    string LoginName { get; set; }
    ...
}

public class User : IUser {
    ...implementation...
}
转换器:

public class InterfaceExtractorJsonConverter<T> : JsonConverter {
    private class InterfaceDictionary<T> : Dictionary<string, object> { }

    private PropertyInfo[] InterfaceProperties {
        get { return typeof(T).GetProperties(); }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        var dictionary = new InterfaceDictionary<T>();
        foreach (var property in InterfaceProperties) {
            dictionary[property.Name] = value.GetType().GetProperty(property.Name).GetValue(value, null);
        }
        serializer.Serialize(writer, dictionary);
    }

    private object ReadNestedObject(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        while (reader.TokenType == JsonToken.Comment) {
            if (!reader.Read())
                throw new Exception("Unexpected end.");
        }

        switch (reader.TokenType) {
            case JsonToken.StartObject:
            case JsonToken.StartArray:
                return serializer.Deserialize(reader, objectType);
            case JsonToken.Integer:
            case JsonToken.Float:
            case JsonToken.String:
            case JsonToken.Boolean:
            case JsonToken.Null:
            case JsonToken.Undefined:
            case JsonToken.Date:
            case JsonToken.Bytes:
                return reader.Value;
            default:
                throw new Exception(string.Format("Unexpected token when converting object: {0}", reader.TokenType));
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        var obj = Activator.CreateInstance(objectType);

        while (reader.Read()) {
            switch (reader.TokenType) {
                case JsonToken.PropertyName:
                    string propertyName = reader.Value.ToString();

                    if (!reader.Read())
                        throw new Exception("Unexpected end.");


                    if (!InterfaceProperties.Any(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase))) {
                        reader.Skip();
                        continue;
                    }
                    var property = objectType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

                    var innerObj = ReadNestedObject(reader, property.PropertyType, existingValue, serializer);

                    property.SetValue(obj, innerObj, null);
                    break;
                case JsonToken.Comment:
                    break;
                case JsonToken.EndObject:
                    return obj;
            }
        }
        throw new Exception("Unexpected end.");
    }

    public override bool CanConvert(Type objectType) {
        return objectType.GetInterfaces().Contains(typeof(T));
    }
}
公共类接口ExtractorJSONConverter:JsonConverter{
私有类接口目录:字典{}
私有财产信息[]接口财产{
获取{return typeof(T).GetProperties();}
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器){
var dictionary=newinterfacedictionary();
foreach(InterfaceProperties中的var属性){
dictionary[property.Name]=value.GetType().GetProperty(property.Name).GetValue(value,null);
}
序列化器。序列化(编写器、字典);
}
私有对象ReadNestedObject(JsonReader读取器,类型objectType,对象existingValue,JsonSerializer序列化程序){
while(reader.TokenType==JsonToken.Comment){
如果(!reader.Read())
抛出新异常(“意外结束”);
}
开关(reader.TokenType){
案例JsonToken.StartObject:
案例JsonToken.StartArray:
返回序列化程序。反序列化(读取器,objectType);
案例JsonToken.Integer:
case JsonToken.Float:
case JsonToken.String:
案例JsonToken.Boolean:
案例JsonToken.Null:
案例JsonToken。未定义:
案例JsonToken。日期:
案例JsonToken.Bytes:
返回reader.Value;
违约:
抛出新异常(string.Format(“转换对象时意外的标记:{0}”,reader.TokenType));
}
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序){
var obj=Activator.CreateInstance(objectType);
while(reader.Read()){
开关(reader.TokenType){
案例JsonToken.PropertyName:
string propertyName=reader.Value.ToString();
如果(!reader.Read())
抛出新异常(“意外结束”);
if(!InterfaceProperties.Any(p=>p.Name.Equals(propertyName,StringComparison.OrdinalIgnoreCase))){
reader.Skip();
继续;
}
var property=objectType.GetProperty(propertyName,BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var innerObj=ReadNestedObject(reader,property.PropertyType,existingValue,serializer);
SetValue(obj,innerObj,null);
打破
案例JsonToken。评论:
打破
案例JsonToken.EndObject:
返回obj;
}
}
抛出新异常(“意外结束”);
}
公共覆盖布尔CanConvert(类型objectType){
返回objectType.GetInterfaces().Contains(typeof(T));
}
}

可以对转换器进行很多优化…

谢谢!流畅的Json看起来很有趣,我会考虑使用它而不是Json.net。自定义转换器可能是一个选项,但我将它作为最后手段。但是KeyValuePair是无用的,或者我不知道你到底想怎么使用它。