Search code examples
c#genericsgeneric-programming

is there a way to pass unknown amount of types to generic method in C#?


I have a method

void InitAndLoadTables(DbConnection cnctn, Dictionary<string, DbTableLoadParameters> tableNamesAndParameters)

where dictionary can have any amount of tables. Every table corresponds a class.

When I iterate through all the tables I would like to call generic method

public void Init<T>(string tableName)

for all the tables. I tried to include type of the class to be property of DbTableLoadParameters as

Type ObjectType { get; set; }

and use that when calling Init. This does not work. So is it even possible to do? If the amount of tables would be fixed I could maybe make InitAndLoadTables generic like

InitAndLoadTables<T, K, V>

but it isn't. So is only possibility to call Init elsewhere like

Init<Orders>("Orders");

Thanks & BR -Matti


Solution

  • There is no way to pass an arbitrary number of type arguments to a generic method, because a generic method always has a fixed number of type arguments.

    However, you don't even seem to need that. There is a way to call a generic method with a runtime-known type, but this involves reflection, which sounds like it's what you're really after:

    class Program
    {
        static void Main(string[] args)
        {
            var myobj = new MyClass();
    
            // Call MyClass.Init<Orders>
            CallMyClassInit(typeof(Orders), "tableOrders");
    
            // Call Init<string>
            CallMyClassInit(typeof(string), "tableString");
        }
    
        static void CallMyClassInit(MyClass obj, Type type, string tableName)
        {
            typeof(MyClass)
                .GetMethod("Init")
                .MakeGenericMethod(type)
                .Invoke(obj, new object[] { tableName });
        }
    }
    
    class Orders { }
    
    class MyClass
    {
        public void Init<T>(string tableName)
        {
            Console.WriteLine("I was called with type " + typeof(T) + " for table " + tableName);
        }
    }
    

    Output:

    I was called with type ConsoleApplication1.Orders for table tableOrders
    I was called with type System.String for table tableString