序列化自定义属性值



给定以下类:

public class PayrollReport
{
    [UiGridColumn(Name = "fullName",Visible = false,Width = "90")]
    public string FullName { get; set; }
    [UiGridColumn(Name = "weekStart", CellFilter = "date")]
    public DateTime WeekStart { get; set; }
}

这个自定义属性

[AttributeUsage(AttributeTargets.All)]
public class UiGridColumn : Attribute
{
    public string CellFilter { get; set; }
    public string DisplayName { get; set; }
    public string Name { get; set; }
    public bool Visible { get; set; }
    public string Width { get; set; }
}

我想为每个字段创建一个仅包含所提供值的List<UiGridColumn>(我不希望跳过的属性为空)。

是否可以创建一个List<UiGridColumn>,其中每个List项只有提供的值?(我担心这是不可能的,但我想我应该问一下)如果可以,怎么做?

如果没有,我的第二个首选是像这样的字符串数组:

[{"name":"fullName","visible":false,"width":"90"},{"name":"weekStart","cellFilter":"date"}]

我宁愿不循环通过每个propertyattributeargument手动构建所需的JSON字符串,但我还没能找到一个简单的方法来做到这一点。

public List<Object> GetUiGridColumnDef(string className)
{
    Assembly assembly = typeof(DynamicReportService).Assembly;
    var type = assembly.GetType(className);
    var properties = type.GetProperties();
    var columnDefs = new List<object>();
    foreach (var property in properties)
    {
        var column = new Dictionary<string, Object>();
        var attributes = property.CustomAttributes;
        foreach (var attribute in attributes)
        {
            if (attribute.AttributeType.Name != typeof(UiGridColumn).Name || attribute.NamedArguments == null)
                    continue;
            foreach (var argument in attribute.NamedArguments)
            {
                column.Add(argument.MemberName, argument.TypedValue.Value);
            }
        }
        columnDefs.Add(column);
    }
    return columnDefs;
}

有更好的方法吗?

如果我正确理解了你的问题,你想序列化应用于类属性的属性列表吗?

如果是这样,你可以创建一个辅助方法来完成:

public static string SerializeAppliedPropertyAttributes<T>(Type targetClass) where T : Attribute
{
    var attributes = targetClass.GetProperties()
                                .SelectMany(p => p.GetCustomAttributes<T>())
                                .ToList();
    JsonSerializerSettings settings = new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Ignore,
        Formatting = Formatting.Indented
    };
    return JsonConvert.SerializeObject(attributes, settings);
}

然后像这样使用:

string json = SerializeAppliedPropertyAttributes<UiGridColumn>(typeof(PayrollReport));

你最终会得到这样的输出,这与你想要的非常接近:

[
  {
    "Name": "fullName",
    "Visible": false,
    "Width": "90",
    "TypeId": "UiGridColumn, JsonTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  },
  {
    "CellFilter": "date",
    "Name": "weekStart",
    "Visible": false,
    "TypeId": "UiGridColumn, JsonTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  }
]

您将注意到包含了来自基本Attribute类的TypeId属性,并且属性名称也没有驼峰大小写。要解决这个问题,您需要使用自定义契约解析器:

public class SuppressAttributeTypeIdResolver : CamelCasePropertyNamesContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        if (member.DeclaringType == typeof(Attribute) && member.Name == "TypeId")
        {
            prop.ShouldSerialize = obj => false;
        }
        return prop;
    }
}

将解析器添加到helper方法中的序列化设置中,您应该可以开始了:

    JsonSerializerSettings settings = new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Ignore,
        ContractResolver = new SuppressAttributeTypeIdResolver(),
        Formatting = Formatting.Indented
    };
现在输出应该是这样的:
[
  {
    "name": "fullName",
    "visible": false,
    "width": "90"
  },
  {
    "cellFilter": "date",
    "name": "weekStart",
    "visible": false
  }
]

演示小提琴:https://dotnetfiddle.net/2R5Zyi

相关内容

  • 没有找到相关文章

最新更新