问题描述
我有类型的对象的 X 后,我可以(显然)在运行时检索。
I have an object of type X, which I can (obviously) retrieve in runtime.
var type = myObject.GetType();
和我有一个通用的静态类。
And I have a generic static class.
public static class MyStaticClass<T>
{
public static void DoStuff(T something)
{
// bla bla
}
}
我想要做的是:
MyStaticClass<myObject.GetType()>.DoStuff(myObject);
但我不能。
But I can't.
事实上,仅仅是上MyStaticClass将经营几类,和他们分享几个接口。一个解决办法是写:
In fact, there is just a few types on which MyStaticClass would operate, and they share several interfaces. One workaround is to write:
if (myObject.GetType() == typeof(X))
{
MyStaticClass<X>.DoStuff(myObject as X);
}
if (myObject.GetType() == typeof(Y))
{
MyStaticClass<Y>.DoStuff(myObject as Y);
}
但它的冗长,编写到处实在是太丑了 - 我觉得我不应该这样做,但也不要我的有无的做到这一点。
我无法相信这是没有办法了。或者有什么解决办法整洁至少?或者是我的方法不对,开始(有什么选择,如果这样)?我应该创建一些(抽象?)基类X,Y,Z?
I can't believe there is no solution. Or any neater workaround at least? Or is my approach wrong to start with (what's the alternative if so)? Should I create some (abstract?) base class for X, Y, Z?
推荐答案
您可以用反射做到这一点,使用 Type.MakeGenericType
- 但是你的也的需要使用反射来调用方法。这是一个有点痛,虽然
You can do this with reflection, using Type.MakeGenericType
- but then you'll also need to use reflection to invoke the method. That's a bit of a pain though.
如果您正在使用C#4你可以使用动态类型和类型推断 - 虽然这仅适用于普通的方法的而不是一般的类型的,所以你需要使用:
If you're using C# 4 you could use dynamic typing and type inference - although that only works for generic methods rather than generic types, so you'd need to use:
public void DoStuffDynamic(dynamic item)
{
DoStuffHelper(item);
}
private static void DoStuffHelper<T>(T item)
{
MyClass<T>.DoStuff(item);
}
编辑:出于性能考虑,你能避免做过多的实际反映。您可以执行反射的一次的每个产品类型,创建表单行动℃的代表;对象>
,并在字典中进行缓存。这可能是的据的不是在每次执行的执行反映速度更快
For performance, you can avoid doing too much actual reflection. You can perform reflection once per item type, create a delegate of the form Action<object>
, and cache it in a dictionary. This can be far faster than performing reflection on every execution.
下面是一个简短但完整的示例:
Here's a short but complete sample:
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);
}
}
在我的有无的,但偶尔也有真的没有任何明智的选择。
I only use this sort of thing when I have to, but occasionally there really isn't any sensible alternative.
这篇关于通用静态类 - 在运行时检索对象类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!