Home > Mobile >  C# How To Initialize a generic Class with a type variable
C# How To Initialize a generic Class with a type variable

Time:09-15

disclaimer I'm a newbie in understanding Reflection.

abstract class BaseClass<T>
    {
        public abstract T Value { get; }
        public virtual bool CheckValue(string input)
        {
            return true;
        }
    }

    class NotBaseClassA : BaseClass<string>
    {
        public override string Value { get => "Yes";}
        public override bool CheckValue(string input)
        {
            return 1 == 2;
        }
    }

    class NotBaseClassB : BaseClass<int>
    {
        public override int Value { get => 1; }
    }

    class ManyBaseClasses
    {
        public NotBaseClassB notBaseClassB;
        public NotBaseClassA notBaseClassA;
    }


    class Programm
    {
        public void Main()
        {
            foreach (PropertyInfo pi in typeof(ManyBaseClasses).GetProperties())
            {
                string input = Console.ReadLine();
                //Get the generic type of the propertyInfo
                //BaseClass<type> bt = new BaseClass<type>();
                //Instantiate BaseClass not as a var So I can do 
                //BaseClass.CheckValue(input)

            }
        }
    }

I'm just trying to do like the title says. So i saw this answer but the answer returns a 'var' but I cant call my CheckValue() function from a type var. (Or i dont think I can?). What i Need is to Instantiate my BaseClass<> with the correct type from a type variable and not as a var, as a proper BaseClass obj so i can then call my functions.

Edit 1 : i've already managed to get the generic type in the variable by doing something like that

public static System.Type GetBaseClassType(this System.Type type)
        {
            System.Type[] types = new System.Type[]{ };
            while (type != null && type != typeof(object) || types.Length == 0)
            {
                types = type.GetGenericArguments();
                
                if (types.Length > 0)
                {
                    return types[0];
                }
                type = type.BaseType;
            }
            return null;
        }

CodePudding user response:

The base class is not relevant in this case, as it's abstract, so you actually want to instantiate the derived class.

All you need to do to create it is

Activator.CreateInstance(pi.PropertyType)

Then you will need to use reflection on that result to call CheckValue, because there is no common base type or interface.

It might be easier to extract the non-generic code into a BaseBaseClass which is not generic, which means you don't need reflection for the second step.

abstract class BaseBaseClass
{
    public virtual bool CheckValue(string input)
    {
        return true;
    }
}

abstract class BaseClass<T> : BaseBaseClass
{
    public abstract T Value { get; }
}

Then you can just do

((BaseBaseClass) Activator.CreateInstance(pi.PropertyType)).CheckValue(someInput)

CodePudding user response:

I've done that before, but it was a long time ago. You have to create instance via reflection and call the method via reflection.

        foreach (PropertyInfo pi in typeof(ManyBaseClasses).GetProperties())
        {
            string input = Console.ReadLine();
            //Get the generic type of the propertyInfo
            var propType = pi.Type;
            Type[] typeArgs = { propType };
            var genType = d1.MakeGenericType(typeArgs);
            //BaseClass<type> bt = new BaseClass<type>();
            object bt = Activator.CreateInstance(genType);
            //Instantiate BaseClass not as a var So I can do 
            //BaseClass.CheckValue(input)
            MethodInfo method = typeof(bt).GetMethod("CheckValue"));
            method.Invoke(bt, new[] { input });
        }
  • Related