I am trying to write a generic class to cast query string passed into a blazor page into a plain c# class. I want to reuse this, rather than specifying specific querystring parameters on every page declaration.
So far I am using reflection and generics but I'm getting an error when trying to pass the property type to the underlying extension methods;
Generic conversion class;
public static TSearchParams GetSearchParamsFromQueryString<TSearchParams>(this Uri uri) where TSearchParams : SearchParams, new()
{
var searchParams = new TSearchParams();
foreach (PropertyInfo prop in searchParams.GetType().GetProperties())
{
var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
if (type == typeof(Enum) || type.IsEnum)
{
prop.SetValue(searchParams, uri.GetEnumFromQueryString<prop.PropertyType> (prop.Name));
}
else
{
prop.SetValue(searchParams, uri.GetValueFromQueryString<prop.PropertyType>(prop.Name);
}
}
This is failing when I try to use prop.PropertyType
in uri.GetEnumFromQueryString<prop.PropertyType> (prop.Name));
for both get values and get enum.
Other relevent code;
POCO class
public class MySearchParameters: SearchParams
{
public MyEnumType? MyEnum { get; set; }
public DateTime? DateStart { get; set; }
public long? BranchId { get; set; }
///.. other types removed for brevity
}
To extract a specific value from a URI (this works in isolation);
public static T GetValueFromQueryString<T>(this Uri uri, string key)
{
if (QueryHelpers.ParseQuery(uri.Query).TryGetValue(key, out var valueFromQueryString))
{
if (typeof(T) == typeof(int?) && int.TryParse(valueFromQueryString, out var valueAsInt))
{
return (T)(object)valueAsInt;
}
if (typeof(T) == typeof(long?) && long.TryParse(valueFromQueryString, out var valueAsLong))
{
return (T)(object)valueAsLong;
}
///.. other types removed for brevity
// otherwise get a string
return (T)(object)valueFromQueryString.ToString();
}
return default(T);
}
To extract an enum from a URI (this works in isolation);
public static Nullable<TEnum> GetEnumFromQueryString<TEnum>(this Uri uri, string key) where TEnum : struct
{
if (QueryHelpers.ParseQuery(uri.Query).TryGetValue(key, out var valueFromQueryString))
{
TEnum res = (TEnum)Enum.Parse(typeof(TEnum), valueFromQueryString);
if (!Enum.IsDefined(typeof(TEnum), res)) return null;
return res;
}
return null;
}
What is the correct way to cast the types during relfection? Or, is there a simpler way to convert all QueryString parameters to a C# class?
Aucun commentaire:
Enregistrer un commentaire