在运行时创建未知泛型类Type对象的实例?

时间:2010-01-30 09:02:40

标签: c# .net

(我确定已经回答过了,我搜索过但找不到了)

我需要在运行时创建几个泛型类型的实例。也就是说,我有一个名为i的变量,它包含一个介于0-4之间的数字,我需要为Action<>,{{创建 Type 对象的实例。 1}},Action<T1>Action<T1, T2>Action<T1, T2, T3>取决于数字是多少(真实情况并非如此简单,以至于它真的在0-4之间,我可以使用切换声明)。

修改:澄清我需要该类型的 Type 对象,而不是该类型的实例。

5 个答案:

答案 0 :(得分:3)

我能想到的最通用的方法是通过名称加载目标操作类型,其中反引号后面的数字(又名grave accent)表示您需要的通用参数的数量。

不幸的是,Action<>在与其他操作类型不同的程序集(mscorlib)中找到,因此在使用此方法时需要对其进行不同的处理。

public static Type GetActionDelegateType(params Type[] typeArgs)
{
    var argCount = typeArgs.Length;
    if (argCount == 0) return typeof (Action);
    var defType = argCount == 1
        ? typeof (Action<>) //special case since it's found in mscorlib
        : Type.GetType(string.Format("System.Action`{0}, {1}",
            argCount,
            typeof (Action).Assembly.FullName));
    return defType.MakeGenericType(typeArgs);
}

您可以使用此测试代码查看上述代码:

for (var i = 0; i <= 4; i++)
{
    var typeArgs = Enumerable.Repeat(typeof (string), i).ToArray();
    Console.WriteLine(GetActionDelegateType(typeArgs));
}

答案 1 :(得分:0)

我不确定我是否完全明白你想要实现的目标。我会猜测。

如果您知道所需的类型参数数量永远不会超过4,那么您可以创建一个数组

Type[] types = new Type[] { typeof(Action<>), typeof(Action<,>), typeof(Action<,,>) }; // omitted the rest

并提供功能

int CalculateNumberOfParameters(int i)
{     
    // I don't know what your i variable really means, but I suggest you have some method to determine a number of type parameters from it).
}

然后你只需使用[CalculateNumberOfParameters(i)]类型来获取你的动作类型。请注意,我提供了一组非参数化泛型,因此您应该在它们上调用MakeGenericType()来创建实际的可实例化类型。如果您事先知道通用参数(并且它们不依赖于i),则应在类型数组创建时指定它们。

如果你永远不知道你需要多少通用参数,你必须在运行时创建类型,因为.net只定义具有0-4参数的Action。您仍然必须为其中一种标准类型提供转换(或适配器),因此您创建的类型的实例实际上可以从应用程序的其他部分使用。这是一条艰难的路线,我只需要使用一次(对于linq表达式序列化),所以除非特别要求,否则我不会深入细节。

答案 2 :(得分:-1)

使用Activator.CreateInstance(string assembly, string classname)

“程序集”可以为null(在本例中为类类型在当前程序集中搜索)。 “classname”应表示类名,您可以从整数或您拥有的任何信息中获得该类名称。

对于模板类,使用classif字符串形式“ClassName'T1”。

答案 3 :(得分:-1)

在类(静态方式)上使用typeof(Action<...>)或在实例上使用GetType()方法(动态方式)。

答案 4 :(得分:-1)

不太确定你在寻找什么,你从未提及你会从哪里获得T1,T2,T3?

此代码可能对您有所帮助。

private static void CreateAppropriateAction(params Type[] argTypes)
        {
            var numberOfArgs = argTypes.Count();
            switch (numberOfArgs)
            {
                case 1:
                    var oneArgAction = typeof(Action<>).MakeGenericType(argTypes);
                    break;
                case 2:
                    var twoArgAction = typeof(Action<,>).MakeGenericType(argTypes);
                    break;
                case 3:
                    var threeArgAction = typeof(Action<,,>).MakeGenericType(argTypes);
                    break;
                default:
                //Do nothing or throw exception
                    break;
            }
        }              

然后你可以使用这个方法进行这样的调用......

CreateAppropriateAction(typeof(string),typeof(int));