I want something like the following:
using System;
using System.Text;
using System.Text.Json;
public class Program
{
public static void Main()
{
var myArgs = new ArgClass();
// myArgs is populated via System.Text.Json deserialization
Console.WriteLine(myArgs.ToArguments());
}
}
public interface IArguments {}
public class ArgClass : IArguments
{
[JsonPropertyName("propertyA")]
public string PropA {get; set;}
[JsonPropertyName("propertyA")]
public int PropB {get; set;}
}
public static class IArgumentsExt
{
public static string ToArguments(this IArguments ArgObj)
{
var argString = new StringBuilder();
//Code to build argument string
return argString.ToString();
}
}
So that the Console.Writeline()
would output the following string:
-argument propertyA="some text" -argument propertyB=123
I feel like this is something that has to be done with reflection, but I know nothing about reflection. I have tried really hard to avoid situations that require it because everything I read (or watch) says it's slow.
The reason I want to do it like this is that the JSON string that I am deserializing has more properties that I am interested in at to moment, but I might want to use more of them in the future; like if I add more features to my app later. As it stands I can add PropC
to ArgClass
to pick up another JSON property. In which case I would want the new output of ToArguments()
to be:
-argument propertyA="text a" -argument propertyB=123 -argument propertyC="text c"
without having to modify ToArguments()
.
Or maybe make another class:
public class OtherArgClass : IArguments
{
[JsonPropertyName("propertyD")]
public string PropD {get; set;}
[JsonPropertyName("propertyE")]
public int PropE {get; set;}
}
and have an output of myOtherArgs.ToArguments()
:
-argument propertyD="some other text" -argument propertyE=45.678
again, without modifying ToArguments()
.
I am using .Net 7 Preview and System.Text.Json (not Newtonsoft/Json.net)
CodePudding user response:
Yes, System.Reflection is needed to achieve your required value.
Get the properties of the instance which applies the
JsonPropertyName
attribute.Iterate the properties.
2.1. Get the property name from the
JsonPropertyName
attribute.2.2. Get the property value and serialize.
2.3. Add both values into
StringBuilder
.
using System.Reflection;
using System.Linq;
public static class IArgumentsExt
{
public static string ToArguments(this IArguments ArgObj)
{
var argString = new StringBuilder();
PropertyInfo[] props = ArgObj.GetType().GetProperties()
.Where(x => x.CustomAttributes.Any(y => y.AttributeType.Name == nameof(JsonPropertyNameAttribute)))
.ToArray();
foreach (PropertyInfo prop in props)
{
string propertyName = ((JsonPropertyNameAttribute)prop.GetCustomAttribute(typeof(JsonPropertyNameAttribute))).Name;
// Or
// string propertyName = prop.GetCustomAttribute<JsonPropertyNameAttribute>().Name;
string propertyValue = JsonSerializer.Serialize(prop.GetValue(ArgObj));
argString.Append($"-argument {propertyName}={propertyValue} ");
}
return argString.ToString()
.Trim();
}
}