(我确定已经回答过了,我搜索过但找不到了)
我需要在运行时创建几个泛型类型的实例。也就是说,我有一个名为i
的变量,它包含一个介于0-4之间的数字,我需要为Action<>
,{{创建 Type 对象的实例。 1}},Action<T1>
,Action<T1, T2>
或Action<T1, T2, T3>
取决于数字是多少(真实情况并非如此简单,以至于它真的在0-4之间,我可以使用切换声明)。
修改:澄清我需要该类型的 Type 对象,而不是该类型的实例。
答案 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));