Как я могу получить список созданных универсальных типов? - PullRequest
0 голосов
/ 23 декабря 2010

Я работаю над проектом (использующим 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, и я пометил их содержащий класс с помощью специального атрибута, говорящего так.Сгенерированная «карта ввода» добавляется в список карт ввода, которые обновляются каждый кадр в игре.Когда комбинация ввода (которая может быть щелчком мыши, движением колеса прокрутки, движением мыши и т. Д., В зависимости от типа отображения ввода) выполняется, событие вызывается и обрабатывается методами, перечисленными в XMLfile.


Чтобы найти методы, на которые ссылается XML-файл, я изначально планировал перебирать экспортируемые типы в выполняющейся сборке с использованием отражения, находить статические классы, к которым был применен мой пользовательский атрибути сохраните все свои открытые статические методы, которые соответствуют сигнатуре делегата рассматриваемого события, в Словаре, используя их имена для использования при последующей загрузке входной карты, ссылающейся на те же методы.Для сборки выпуска я напишу этот список методов в файл, чтобы существенно сократить время загрузки, но для отладки я хочу, чтобы этот список доступных обработчиков событий оставался в курсе моих ревизий.

Это работает отлично, и на удивление занимает меньше времени, чем я ожидал.Однако я не могу понять, как расширить этот подход для включения общих делегатов: у меня есть универсальный делегат с именем 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.
        */
    }
}

, и я хочу иметь возможность просто набрать <Handler>HandleInput</Handler> в моем XML-файле и найти MethodInfo, который соответствуетметод, определенный в классе, построенном из InputHandlers<T> с общим аргументом, соответствующим событию, которое я хочу обработать (того же типа, что и T, используемый в объявлении InputHandler<T> события, которое я могу извлечь только из сборкиимя, указанное в файле XML).

Я знаю (из спецификаций C #), что открытых типов не существует во время выполнения, так как я могу получить список закрытых типов, созданных из моего универсального класса

Ответы [ 2 ]

1 голос
/ 24 декабря 2010

Если я вас правильно понимаю, вам нужно вызвать универсальный метод на основе строковых значений, указанных в вашем 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());
    }
}

Возможно, вы захотите добавить обработку ошибок, проверку нуля и т. Д.

0 голосов
/ 27 декабря 2010

Оказывается, я сильно усложнил эту проблему.Мой настоящий вопрос, хотя я и не знал об этом, состоял в том, как получить обобщенный тип определение (то есть 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>);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...