Kon*_*ski 3 c# generics reflection static
我有一个X类型的对象,我可以(显然)在运行时检索.
var type = myObject.GetType();
Run Code Online (Sandbox Code Playgroud)
我有一个通用的静态类.
public static class MyStaticClass<T>
{
public static void DoStuff(T something)
{
// bla bla
}
}
Run Code Online (Sandbox Code Playgroud)
我想做的是:
MyStaticClass<myObject.GetType()>.DoStuff(myObject);
Run Code Online (Sandbox Code Playgroud)
但我不能.
实际上,MyStaticClass只有几种类型可以运行,它们共享多个接口.一个解决方法是写:
if (myObject.GetType() == typeof(X))
{
MyStaticClass<X>.DoStuff(myObject as X);
}
if (myObject.GetType() == typeof(Y))
{
MyStaticClass<Y>.DoStuff(myObject as Y);
}
Run Code Online (Sandbox Code Playgroud)
但它的冗长和写作处处实在是太丑了-我觉得我不应该这样做,而且,我不应该有这样做.
我无法相信没有解决方案.或者至少有任何整洁的解决方法?或者我的方法开始时是错误的(如果是这样的替代方案)?我应该为X,Y,Z创建一些(抽象?)基类吗?
您可以使用反射来执行此操作Type.MakeGenericType- 但是您还需要使用反射来调用该方法.虽然这有点痛苦.
如果你使用的是C#4,你可以使用动态类型和类型推断 - 虽然这只适用于泛型方法而不是泛型类型,所以你需要使用:
public void DoStuffDynamic(dynamic item)
{
DoStuffHelper(item);
}
private static void DoStuffHelper<T>(T item)
{
MyClass<T>.DoStuff(item);
}
Run Code Online (Sandbox Code Playgroud)
编辑:为了表现,你可以避免做太多的实际反思.您可以对每个项目类型执行一次反射,创建表单的委托Action<object>,并将其缓存在字典中.这比在每次执行时执行反射要快得多.
这是一个简短但完整的样本:
using System;
using System.Collections.Generic;
using System.Reflection;
public static class MyStaticClass
{
private static readonly object mapLock = new object();
private static readonly Dictionary<Type, Action<object>>
typeActionMap = new Dictionary<Type, Action<object>>();
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<object> action;
lock (mapLock)
{
if (!typeActionMap.TryGetValue(type, out action))
{
action = BuildAction(type);
typeActionMap[type] = action;
}
}
action(item);
}
private static Action<object> BuildAction(Type type)
{
MethodInfo generic = helperMethod.MakeGenericMethod(type);
Delegate d = Delegate.CreateDelegate(typeof(Action<object>),
generic);
return (Action<object>) d;
}
private static void ActionHelper<T>(object item)
{
MyStaticClass<T>.DoStuff((T) item);
}
}
public static class MyStaticClass<T>
{
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);
}
}
Run Code Online (Sandbox Code Playgroud)
当我我只用这样的事情有,但偶尔实在是没有任何明智的选择.