在运行时设置generics类型

我上课了

public class A { public static string B(T obj) { return TransformThisObjectToAString(obj); } } 

上面使用字符串纯粹是示范性的。 我可以在已知/指定的类型上调用这样的静态函数:

 string s= A.B(objectOfKnownType); 

如果我事先不知道T ,我该怎么做这个调用,而是我有一个Type类型的变量来保存类型。 如果我这样做:

 Type t= typeof(string); string s= A.B(someStringObject); 

我得到这个编译器错误:

 Cannot implicitly convert type 't' to 'object' 

你不能。 通用类型标识符必须在编译时知道。

编辑

从其他post来看,似乎可以通过动态生成方法并调用它 – 当然这有危险。 有关更多信息,请参阅Thomas’和Dathan的post。

您不能直接执行此操作,但可以使用reflection在运行时提供类的类型参数。 我没有测试过这个,但这样的事情应该有效:

 // We want to do something like this: // object o = "Hello" // Type t = o.GetType(); // // This is pseudo-code only: // string s = A.B(o); string InvokeA(object o) { // Specify the type parameter of the A<> type Type genericType = typeof(A<>).MakeGenericType(new Type[] { o.GetType() }); // Get the 'B' method and invoke it: object res = genericType.GetMethod("B").Invoke(new object[] { o }); // Convert the result to string & return it return (string)res; } 

当然,问题是这是否真的是你需要的 – 如果你对作为参数给出的对象一无所知,你也可以用对象编写整个代码。 但是,我可以想象一些有用的场景,所以我想你可以尝试使用它。

在框架和CLR中绝对支持这一点 – 只是在C#中不优雅。 但是,在辅助方法的帮助下,您可以完成我认为您想要的任务:

 public class A { public static string B(T obj) { return obj.ToString(); } } public class MyClass { public static void DoExample() { Console.WriteLine(ExecuteB("Hi")); Console.WriteLine(ExecuteB(DateTime.Now)); } public static object ExecuteB(object arg) { Type arg_type = arg.GetType(); Type class_type = typeof(MyClass); MethodInfo mi = class_type.GetMethod("ExecuteBGeneric", BindingFlags.Static | BindingFlags.Public); MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { arg_type }); return mi2.Invoke(null, new object[] { arg }); } public static object ExecuteBGeneric(T arg) { return A.B(arg); } 

你不能。 但是你提出了错误的问题。 在这种情况下(如99%的情况),您实际需要的只是一个类型约束

尝试:

 public class A where T : object 

或者,如果T是已知类,子类或接口,那么最好使用它

 public class A where T : YourAbstractClass 

还存在其他类型约束。 更多细节: http : //msdn.microsoft.com/en-us/library/d5x73970(VS.80).aspx

总的来说,在学习一门新语言时,你经常需要广泛地思考你想要达到的目标 ,而不是专门找到你想要做的事情 。 这很像现实世界的口头语言。 通过阅读字典学习德语并将单词强制转换为英语语法,或者学习语法并学习单词来学习德语之间的区别。 是的,德国演讲者会理解一个用字典说话的人,但每句话的WTF要高得多。

试图在运行时替换类型参数会破坏类型安全的整个目的,这是由C#compiler强制执行的.C#编译器确保在编译时指定类型参数,并且在运行时类型参数没有歧义。我怀疑你能不能通用类型中运行时的替换类型参数。类型“ 类型 ”的类型参数类似于具有未绑定的generics类型。

我基于这里的一些答案创建了这个辅助方法,而不是在网络上。

用法:

 InvokeGenericMethodWithRuntimeGenericArguments( MyMethodWithGenericType, new[] {MyRuntimeGenericType}, null); 

方法:

 public static object InvokeGenericMethodWithRuntimeGenericArguments(Action methodDelegate, Type[] runtimeGenericArguments, params object[] parameters) { if (parameters == null) { parameters = new object[0]; } if (runtimeGenericArguments == null) { runtimeGenericArguments = new Type[0]; } var myMethod = methodDelegate.Target.GetType() .GetMethods() .Where(m => m.Name == methodDelegate.Method.Name) .Select(m => new { Method = m, Params = m.GetParameters(), Args = m.GetGenericArguments() }) .Where(x => x.Params.Length == parameters.Length && x.Args.Length == runtimeGenericArguments.Length ) .Select(x => x.Method) .First().MakeGenericMethod(runtimeGenericArguments); return myMethod.Invoke(methodDelegate.Target, parameters); }