Reputation: 3720
I am currently building a wrapper for WkHtmlToPdf to make creating the console switches easier, but I'm looking for the best way to serialize out the properties into their respective switches without having to define a method for each individual switch. Many of the switches are simple bools that if they're set to true need to be included. Is there some manner of using attributes that could simplify the class serialization?
Here's a simplified version of the properties class:
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; }
}
In theory, I could do something with attributes to make it look like the following:
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; }
}
But I'm not quite sure where to start in order to get the switches to generate when the class is serialized/used.
Upvotes: 1
Views: 40
Reputation: 3338
You can either start with Type.GetProperties or with TypeDescriptor.GetProperties, I will use the first for the rest of my answer, so you can start like this:
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);
}
The code assumes that all the attributes are derived from WkAttrBase
and should be enhanced with some checks (e.g. prop.CanRead
and checking that prop.PropertyType
is what you expect).
Upvotes: 1