zs2020
zs2020

Reputation: 54541

How to set the generic variable of the type Type in a loop?

I would like to do some similar process within a loop like this by calling a generic method with different types.

AAA, BBB are all classes. CreateProcessor is a generic method in the class of MyProcessor.

new List<Type> {typeof (AAA), typeof (BBB)}.ForEach(x =>
{
    var processor = MyProcessor.CreateProcessor<x>(x.Name);
    processor.process();
});

This doesn't compile, I got the error saying Cannnot resolve symbol x.

Technically, how to achieve it? (I know the strategy pattern is better...)

Upvotes: 6

Views: 241

Answers (4)

Faraday
Faraday

Reputation: 2954

This is how you would create a new variable using only type information, by using dynamic you are able to call any method which you know exists for all of the types. I would suggest (assuming these types are your own classes) you implement an interface baseclass or something for these if possible, it simplify your quite a lot...

new List<Type> { typeof(string), typeof(int) }.ForEach(x =>
{
    dynamic processor = Activator.CreateInstance(x);
    processor.ToString();
    processor.CallAnyMethodHere();
    processor.Process();
});

Edited code - Adding a clear example

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

public class mainClass
{
    public static void Main(string[] args)
    {
        new List<Type> { typeof(StringBuilder), typeof(Int64) }.ForEach(x =>
        {
            dynamic instance = Activator.CreateInstance(x);

            DoSomething(instance);
        });

        Console.ReadKey();
    }

    public static void DoSomething(StringBuilder stringBuilder)
    {
        Console.WriteLine("StringBuilder overload");
    }


    public static void DoSomething(Int64 int64)
    {
        Console.WriteLine("Int64 overload");
    }
}

Edit 2 - Only call generic method

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq;

public class mainClass
{
    public static void Main(string[] args)
    {
        new List<Type> { typeof(StringBuilder), typeof(Int64) }.ForEach(x =>
        {
            var methodInfoArray = typeof(mainClass).GetMethods();
            var methodInfo = methodInfoArray.First(mi => mi.Name == "DoSomething" && mi.IsGenericMethodDefinition);
            var genericMethod = methodInfo.MakeGenericMethod(new Type[] { x });
            var blah = genericMethod.Invoke(null, new object[] { "Hello" }) as MethodInfo;
        });

        Console.ReadKey();
    }

    public static void DoSomething<T>(string variable)
    {
        Console.WriteLine("DoSomething<T> " + typeof(T) + " overload - " + variable);
    }

    public static void DoSomething(string variable)
    {
        Console.WriteLine("DoSomething - " + variable);
    }

}

Upvotes: 0

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

Sorry, I updated my question. I intended to call a generic method actually.

var method = typeof(MyProcessor).GetMethod("CreateProcessor", new Type[] { typeof(string) });
new List<Type> { typeof(AAA), typeof(BBB) }.ForEach(x =>
{
    dynamic processor = method.MakeGenericMethod(x).Invoke(null, new[] { x.Name });
    processor.process();
});

Upvotes: 7

Hans Passant
Hans Passant

Reputation: 942488

Reflection is required to deal with the Type class:

    new List<Type> { typeof(AAA), typeof(BBB) }.ForEach(x => {
        var type = typeof(MyClass<>).MakeGenericType(x);
        dynamic processor = Activator.CreateInstance(type, x.Name);
        processor.process();
    });

Upvotes: 8

itsme86
itsme86

Reputation: 19526

You have to use reflection to create a generic object like that. This page from Microsoft has an excellent rundown on what you need to do: How to: Examine and Instantiate Generic Types with Reflection

Upvotes: 0

Related Questions