通用静态类 – 在运行时检索对象类型

我有一个X类型的对象,我可以(显然)在运行时检索。

var type = myObject.GetType(); 

我有一个通用的静态类。

 public static class MyStaticClass { public static void DoStuff(T something) { // bla bla } } 

我想做的是:

 MyStaticClass.DoStuff(myObject); 

但我不能。

实际上,MyStaticClass只有几种类型可以运行,并且它们共享多个接口。 一种解决方法是写:

 if (myObject.GetType() == typeof(X)) { MyStaticClass.DoStuff(myObject as X); } if (myObject.GetType() == typeof(Y)) { MyStaticClass.DoStuff(myObject as Y); } 

但它很冗长,写到处都是非常丑陋的 – 我觉得我不应该这样做,但我也不应该这样做。

我无法相信没有解决方案。 或者至少有任何整洁的解决方法? 或者我的方法开始时是错误的(如果是这样的替代方案)? 我应该为X,Y,Z创建一些(抽象?)基类吗?

您可以使用Type.MakeGenericType通过reflection执行此Type.MakeGenericType – 但是您需要使用reflection来调用该方法。 虽然这有点痛苦。

如果你正在使用C#4,你可以使用动态类型和类型推断 – 尽管这只适用于generics方法而不是generics类型 ,所以你需要使用:

 public void DoStuffDynamic(dynamic item) { DoStuffHelper(item); } private static void DoStuffHelper(T item) { MyClass.DoStuff(item); } 

编辑:为了表现,你可以避免做太多的实际反思。 您可以对每个项类型执行一次reflection,创建Actionforms的委托,并将其缓存在字典中。 这比在每次执行时执行reflection快得多。

这是一个简短但完整的样本:

 using System; using System.Collections.Generic; using System.Reflection; public static class MyStaticClass { private static readonly object mapLock = new object(); private static readonly Dictionary> typeActionMap = new Dictionary>(); private static readonly MethodInfo helperMethod = typeof(MyStaticClass).GetMethod("ActionHelper", BindingFlags.Static | BindingFlags.NonPublic); public static void DoStuffDynamic(object item) { if (item == null) { throw new ArgumentNullException("item"); } Type type = item.GetType(); Action action; lock (mapLock) { if (!typeActionMap.TryGetValue(type, out action)) { action = BuildAction(type); typeActionMap[type] = action; } } action(item); } private static Action BuildAction(Type type) { MethodInfo generic = helperMethod.MakeGenericMethod(type); Delegate d = Delegate.CreateDelegate(typeof(Action), generic); return (Action) d; } private static void ActionHelper(object item) { MyStaticClass.DoStuff((T) item); } } public static class MyStaticClass { public static void DoStuff(T something) { Console.WriteLine("DoStuff in MyStaticClass<{0}>", typeof(T)); } } public class Test { static void Main() { MyStaticClass.DoStuffDynamic("Hello"); MyStaticClass.DoStuffDynamic(10); } } 

我必须使用这种东西,但偶尔也没有任何明智的选择。

“实际上,MyStaticClass只有几种类型可以运行,并且它们共享多个接口。一种解决方法是编写:”

所以你不能针对共享interface编写DoStuff方法吗? 这样您就可以针对已知接口进行编程,而不是试图猜测对象的类型。 整个方法看起来有点狡猾。 然后你可以完全删除generics。

如果没有reflection,这是不可能的,必须在编译时知道generics类型参数。 即使有可能通过反思,我也会反对。 你应该改变你的设计。