使用属性使类的序列化变得容易吗?

时间:2018-09-20 16:50:44

标签: c# serialization attributes

我目前正在为WkHtmlToPdf构建包装程序,以使创建控制台开关更加容易,但是我正在寻找将属性序列化到其各自开关中的最佳方法,而不必为每个单独的开关定义方法。许多开关都是简单的布尔值,如果将它们设置为true,则需要包括在内。是否有某种使用属性的方式可以简化类的序列化?

这是属性类的简化版本:

public class PdfOptions
{
    public bool Book { get; set; }
    public bool Collate { get; set; }
    public Dictionary<string, string> Cookies { get; set; }
    public string CoverUrl { get; set; }
    public Dictionary<string, string> CustomHeaders { get; set; }
    public bool DebugJavascript { get; set; }
    public bool DefaultHeader { get; set; }
    public bool DisableExternalLinks { get; set; }
    public bool DisableInternalLinks { get; set; }
    public bool DisableJavascript { get; set; }
}

从理论上讲,我可以对属性做一些事情,使其看起来像以下内容:

public class PdfOptions
{
    [WkSwitch(Name = "--book")]
    public bool Book { get; set; }
    [WkSwitch(Name = "--collate")]
    public bool Collate { get; set; }
    [WkCollectionSwitch(Name = "--cookie {key} {value}")]
    public Dictionary<string, string> Cookies { get; set; }
    [WkValueSwitch(Name = "--collate {value}")]
    public string CoverUrl { get; set; }
    [WkCollectionSwitch(Name = "--custom-header {key} {value}")]
    public Dictionary<string, string> CustomHeaders { get; set; }
    [WkSwitch(Name = "--debug-javascript")]
    public bool DebugJavascript { get; set; }
    [WkSwitch(Name = "--default-header")]
    public bool DefaultHeader { get; set; }
    [WkSwitch(Name = "--disable-external-links")]
    public bool DisableExternalLinks { get; set; }
    [WkSwitch(Name = "--disable-internal-links")]
    public bool DisableInternalLinks { get; set; }
    [WkSwitch(Name = "--disable-javascript ")]
    public bool DisableJavascript { get; set; }
}

但是我不太确定从哪里开始才能使在序列化/使用该类时生成开关。

1 个答案:

答案 0 :(得分:1)

您可以以Type.GetPropertiesTypeDescriptor.GetProperties开头,我将使用第一个答案,因此您可以这样开始:

var options = new PdfOptions() { ... };
var builder = new StringBuilder();
foreach(var prop in options.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
    var attrs = prop.GetCustomAttributes(typeof(WkAttrBase), false);
    if (attrs.Length != 1) continue; // maybe throw if Length > 1
    switch(attrs[0]) {
    case WkSwitch sw:
        if(prop.GetValue(options) == true) {
            if(builder.Length > 0) builder.Append(" ");
            builder.Append(sw.Name);
        }

该代码假定所有属性均源自WkAttrBase,并应通过一些检查(例如prop.CanRead并检查prop.PropertyType是否符合您的期望)进行增强。