Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does calling MakeGenericType(...) multiple times create a new type every time?

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;
    }
}
like image 985
Tom Avatar asked Aug 29 '17 12:08

Tom


1 Answers

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 by MakeGenericType is the same as the Type obtained by calling the GetType method of the resulting constructed type, or the GetType 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
like image 183
Sergey Kalinichenko Avatar answered Nov 06 '22 12:11

Sergey Kalinichenko