I have an Entity Framework Code First model for which I made a static generic class which has a search method which is called for every item in a list. Admitting that this is over my head, I thought making the class static would improve code clarity and maybe even performance as one does not have to create instances in many different places. The goal of all of this is to automate which properties can be searched, exported, etc by the user.
The primary question is: If MakeGenericType(...) is called for every item (potentially 1000s) which has a reference type property, is a generic type for that reference type property generated once and saved somewhere or generated 1000s of times?
Pointing out any other performance crimes or code smells is appreciated.
public static class SearchUserVisibleProperties<T>
{
private static List<PropertyInfo> userVisibleProperties { get; set; }
static SearchUserVisibleProperties()
{
userVisibleProperties = typeof(T).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(UserVisibleAttribute))).ToList();
}
public static bool search(T item, string searchString)
{
foreach (PropertyInfo pInfo in userVisibleProperties)
{
object value = pInfo.GetValue(item);
if (value == null)
{
continue;
}
if (pInfo.PropertyType == typeof(string) || pInfo.PropertyType.IsValueType)
{
...unrelevant string matching code...
}
else if ((bool)typeof(SearchUserVisibleProperties<>).MakeGenericType(new Type[] { value.GetType() }).InvokeMember(nameof(search), BindingFlags.InvokeMethod, null, null, new object[] { value, searchString }))
{
return true;
}
}
return false;
}
}
Documentation of MakeGenericType
suggests that the type returned for the same combination of generic type definition and generic type arguments will be the same:
The
Type
object returned byMakeGenericType
is the same as theType
obtained by calling theGetType
method of the resulting constructed type, or theGetType
method of any constructed type that was created from the same generic type definition using the same type arguments.
Here is a small experiment to show that the above is correct:
var a = typeof(Tuple<,>).MakeGenericType(typeof(int), typeof(char));
var b = typeof(Tuple<,>).MakeGenericType(typeof(int), typeof(char));
var c = typeof(Tuple<int,char>);
Console.WriteLine(ReferenceEquals(a, b)); // True
Console.WriteLine(ReferenceEquals(a, c)); // True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With