如何获取构建的泛型类型列表?

时间:2010-12-23 20:42:28

标签: generics reflection xna

我正在开发一个项目(使用Xna),基本上,它读取XML内容文件以创建处理各种类型输入事件的事件处理程序。 XML文件看起来像这样:

<InputMapping>
  <InputType>Microsoft.Xna.Framework.Input.Keys, Microsoft.Xna.Framework, Version=3.1.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d</InputType>
  <Combination>Up W</Combination>
  <CombinationType>Any</CombinationType>
  <Handlers>
    <Handler>MoveUp</Handler>
    <Handler>ScrollMenuUp</Handler>
  </Handlers>
</InputMapping>

“MoveUp”和“ScrollMenuUp”是我希望能够处理按下“向上”和/或“W”键时引发的事件的两种方法的名称,并且我已经标记了它们的包含类使用自定义属性这样说。生成的“输入地图”被添加到输入地图列表中,该列表在游戏中的每一帧都被更新。当满足输入组合(可以是鼠标按钮单击,滚轮移动,鼠标移动等,取决于输入映射的类型)时,会引发事件并通过XML中列出的方法处理文件。


为了找到XML文件引用的方法,我的计划最初是使用反射迭代执行程序集中的导出类型,找到应用了我的自定义属性的静态类,并存储它们的所有公共静态在Dictionary中匹配相关事件的委托签名的方法,由其名称键入,以供引用相同方法的后续输入映射加载使用。对于发布版本,我会将这个方法列表写入文件以大大减少加载时间,但是对于调试,我希望这个可用事件处理程序列表能够与我的修订保持同步。

这非常有效,并且比我预期的要少得多。但是,我无法弄清楚如何扩展这种方法以包含泛型委托:我有一个名为InputHandler<T>的通用委托,如下所示:

public delegate void InputHandler<T>(T input, GameTime gameTime) where T : struct;

我可以很好地获得委托的签名,但我的问题是我不知道如何获取由包含可能由InputHandler<T>表示的方法的泛型类型构造的类。用更简单的术语来说,我有一个名为InputHandlers<T>的类,如下所示:

[MyInputHandlerAttribute]//This tells my XML-loading method to look in this class for event handler candidates
public static class InputHandlers<T>
    where T : struct
{
    public static void HandleInput<T>(T input, GameTime gameTime)
    {
        /*
        * An input event would be handled here.
        * The type of input event handled would depend entirely on the assembly-qualified
        * name provided in the "<InputType>" element of the XML file.
        * This kind of non-specific input handling might not make sense, but it has its worthwhile uses:
        * serializing input for network transmission
        * (using some interface that T would be constrained to implement) is the use I have in mind.
        */
    }
}

我希望能够在我的XML文件中简单地键入<Handler>HandleInput</Handler>并找到与从InputHandlers<T>构造的类中定义的方法对应的MethodInfo,其泛型参数对应于事件I我正在寻找处理(与事件的InputHandler<T>声明中使用的T相同,我只能从XML文件中列出的程序集限定名称中获取。)

我知道(根据C#规范)运行时不存在开放类型,那么如何获取从我的泛型类构造的封闭类型列表?

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您需要根据XML文件中指定的字符串值调用泛型方法。这样就可以了:

void Main() {
    HandleEvent ("WindowsBase", "System.Windows.Input.Key");
    // I dont have XNA, so I could not test your specific classes
    // HandleEvent ("Microsoft.Xna.Framework",  "Microsoft.Xna.Framework.Input.Keys"); 
}

void HandleEvent(string assemblyName, string typeName)
{   
    var instance = Assembly.Load(assemblyName).CreateInstance(typeName);
    Handler.Handle(instance);
}

static class Handler {
    public static void Handle<T>(T input)  {
        Console.WriteLine("Handling input of type: " + input.GetType());
    }
}

您可能希望添加错误处理,空检查等。

答案 1 :(得分:0)

事实证明,这个问题让我大为过于复杂。我真正的问题,虽然我不知道,但是如何使用类型的名称来获得泛型类型定义(即typeof(InputHandlers<>),而没有特定的通用参数)。这很简单:

Type genericDefinition = typeof(<some type in my assembly>).Assembly.GetTypes().Where(t=>(t.IsGenericDefinition && t.Name == <the name I'm looking for>)).First();

使用检索到的类型,只需2个简单的步骤即可获得具有任何类型参数的类型的“构造”版本,然后找到类型中定义的静态方法:

MethodInfo referencedMethod = genericDefinition.MakeGenericType(<the type parsed from the InputType tag of my xml>).GetMethod(<the name of the static method parsed from my xml>);