Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.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
C# 4.0 序列化自定义属性值_C# 4.0_Json.net_Custom Attributes - Fatal编程技术网

C# 4.0 序列化自定义属性值

C# 4.0 序列化自定义属性值,c#-4.0,json.net,custom-attributes,C# 4.0,Json.net,Custom Attributes,鉴于以下类别: 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; } }

鉴于以下类别:

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; }
}
我想为每个字段创建一个
列表
,其中只包含提供的值(我不希望跳过的属性为空)

是否可以创建一个
列表
,其中每个
列表
项仅具有提供的值?(我担心这是不可能的,但我想我会问)如果是,怎么办

如果不是,我的第二个首选项是如下所示的字符串数组:

[{"name":"fullName","visible":false,"width":"90"},{"name":"weekStart","cellFilter":"date"}]
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"
  },
  {
    "cellFilter": "date",
    "name": "weekStart",
    "visible": false
  }
]
我不希望通过循环每个
属性
属性
参数
来手动构建所需的
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;
}
公共列表GetUiGridColumnDef(字符串类名称)
{
Assembly Assembly=typeof(DynamicReportService).Assembly;
var type=assembly.GetType(className);
var properties=type.GetProperties();
var columnDefs=新列表();
foreach(属性中的var属性)
{
var column=newdictionary();
var attributes=property.CustomAttributes;
foreach(属性中的var属性)
{
if(attribute.AttributeType.Name!=typeof(UiGridColumn.Name | | attribute.NamedArguments==null)
继续;
foreach(attribute.NamedArguments中的var参数)
{
添加(argument.MemberName,argument.TypedValue.Value);
}
}
columnDefs.Add(列);
}
返回列defs;
}

有更好的方法吗?

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

如果是这样,您可以创建一个助手方法,如下所示:

[{"name":"fullName","visible":false,"width":"90"},{"name":"weekStart","cellFilter":"date"}]
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"
  },
  {
    "cellFilter": "date",
    "name": "weekStart",
    "visible": false
  }
]
您会注意到包含了基本
属性
类中的
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"},{"name":"weekStart","cellFilter":"date"}]
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"
  },
  {
    "cellFilter": "date",
    "name": "weekStart",
    "visible": false
  }
]

演示小提琴:

这几乎是完美的<代码>可见仅为一个属性定义,但它在两个属性中都显示,因为它是
bool
。当我试图使其
为空时
,我发现
“可见”不是有效的命名属性参数,因为它不是有效的属性参数类型
。建议?您可以使用
DefaultValueHandling=DefaultValueHandling。当设置为默认值
false
时,忽略设置中的
以抑制可见的
。但是,对于第一个对象,这也会抑制它,因为您已将其显式设置为false。不幸的是,使用此解决方案,您不能同时使用这两种方法——要么始终包含值,要么仅在值与默认值不同时才包含值。很高兴知道。我同意跳过默认值。但是,我希望默认情况下
Visible
true
,因此我更改了默认值并添加了
DefaultValueHandling
代码。它完全按照预期工作。谢谢哦,是的,去小熊队!太好了,我很高兴你能按你想要的方式工作。去吧,小熊们!:-)