Разбор классов для методов с пользовательским атрибутом и добавление в список делегатов - PullRequest
0 голосов
/ 03 февраля 2019

Мне нужна помощь в разборе конкретных методов из классов, производных от базового класса, и добавлении их в коллекцию делегатов.

У меня есть несколько классов, производных от одного базового класса.Каждый из этих классов имеет 1 или более методов с определенным пользовательским атрибутом [IntentHandler].Все эти методы имеют один параметр.Тип параметра различается в зависимости от метода, но параметр каждого метода является производным от другого базового класса (открытый класс Intent).Мне нужно найти все эти методы, создать соответствующий делегат и добавить их в делегат «Словарь», где ключ - это тип параметра, а значение - метод.

Прямо сейчас я создаю каждый подкласси регистрация его делегата метода, но есть МНОЖЕСТВО подклассов, каждый из которых требует кода для регистрации своих методов.Я бы предпочел справиться с этим через базовый класс, используя System.Reflection.Это значительно уменьшило бы код и позволило бы улучшить расширение в дальнейшем.

public class StaticService : Service
{
    delegate void ObjectCreatedIntentHandler(ObjectCreatedIntent oci);

    private ObjectCreatedIntentHandler handleObjectCreatedIntent;

    public StaticService()
    {
        handleObjectCreatedIntent = HandleObjectCreatedIntent;
    }

    private void HandleObjectCreatedIntent(ObjectCreatedIntent oci)
    {

    }

    internal override void RegisterIntentHandlers(IntentManager registry)
    {
        registry.RegisterForIntent(typeof(ObjectCreatedIntent), handleObjectCreatedIntent);
    }

    internal override void UnregisterIntentHandlers(IntentManager registry)
    {
        registry.UnregisterForIntent(typeof(ObjectCreatedIntent), handleObjectCreatedIntent);
    }
}

Я бы предпочел что-то более похожее на:

public class StaticService : Service
{
    public StaticService()
    {
    }

    [IntentHandler]
    private void HandleObjectCreatedIntent(ObjectCreatedIntent oci)
    {

    }
}

и базовый класс

public class Service
{
    public Service()
    {
        RegisterIntents()
    }

    private void RegisterIntents()
    {
        // Find all classes derived from Service
        // Find each method in those classes with the [IntentHandler]
        // Attribute
        // Get the method's Intent Class derived parameter type
        // create a delegate I can invoke later for that method.
        // Add the delegate to a Dictionary<Intent,Delegate>;
    }
}

1 Ответ

0 голосов
/ 04 февраля 2019

Я думаю, что нашел решение.Сейчас я использую Action вместо делегата.

В моем базовом классе я сейчас занимаюсь этим:

    internal void RegisterIntentHandlers(IntentManager registry)
    {
        RegisterIntentHandlers(this.GetType(), registry);
    }

    internal void RegisterIntentHandlers(Type klass, IntentManager registry)
    {
        foreach (System.Reflection.MethodInfo m in klass.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
        {
            foreach (Attribute attribute in m.GetCustomAttributes())
            {
                if (attribute is IntentHandler)
                {
                    if (m.GetParameters().Count() == 1)
                    {
                        ParameterInfo p = m.GetParameters()[0];
                        Type paramClass = p.ParameterType;
                        if (paramClass.IsAssignableFrom(typeof(Intent)))
                        {
                            object consumerKey = this.GetType().FullName + "#" + m.Name;
                            Action<Intent> intentConsumer = (Action<Intent>)m.CreateDelegate(typeof(Action<Intent>), this);
                            registry.RegisterForIntent<Intent>(paramClass, consumerKey, intentConsumer);
                            if (!registration.ContainsKey(paramClass))
                                registration[paramClass].Add(consumerKey);
                        }
                    }
                }
            }
        }
    }

Я еще не закончил тестирование, но мне это кажется правильным.Мне нужно очистить все подклассы, прежде чем я смогу закончить тестирование.

Есть какие-либо мнения / предложения?

...