C# Отражение для получения атрибута, прикрепленного к методу реализации интерфейса - PullRequest
0 голосов
/ 03 августа 2020

У меня есть тип TestTopicNotificationHandler, и я sh, чтобы получить атрибуты MessageBusSubscription, прикрепленные к методу handle любого метода ITopicNotificationHandler <>, который реализован внутри класса.

Там пара сценариев ios:

  1. Атрибут может не быть прикреплен к каждой реализации интерфейса, как в приведенном ниже случае с Task Handle(OtherNotification notification)
  2. Я не хочу искать через имя функции Handle, так как в этом случае он будет подбирать Task Handle(bool notAnInterfaceImplementation), который на самом деле не является сигнатурой ITopicNotificationHandler
  3. Он также должен игнорировать сигнатуры методов, которые действительны (с точки зрения ITopicNotificationHandler), но не определены в списке интерфейсов класса

Как я могу достичь вышеуказанного, пожалуйста, найдите связанную реализацию и вытащите из нее атрибут (без отражения по имени метода), как показано ниже:

var type = typeof(TestTopicNotificationHandler);
var attributes = FindAttributes(type);
// above function call returns the attributes that are defined in the class
// { [MessageBusSubscription("v1\test", QualityOfService.AtMostOnce)], [MessageBusSubscription("v1\yes", QualityOfService.AtMostOnce)]

Если это будет типичная реализация класса:

class TestTopicNotificationHandler : ITopicNotificationHandler<TestTopicNotification>, ITopicNotificationHandler<YesNotification>, ITopicNotificationHandler<OtherNotification>
{
    [MessageBusSubscription("v1\test", QualityOfService.AtMostOnce)]
    public Task Handle(TestTopicNotification notification)
    {
    return Task.CompletedTask;
    }
    
    [MessageBusSubscription("v1\yes", QualityOfService.AtMostOnce)]
    public Task Handle(YesNotification notification)
    {
    return Task.CompletedTask;
    }
    
    // this should be ignored as whilst listed, it does not have an attribute attached
    public Task Handle(OtherNotification notification)
    {
        return Task.CompletedTask;
    }

    // this should be ignored as whilst valid interface signature, it is not listed in the implementation list of the class
    public Task Handle(NonListedNotification notification)
    {
        return Task.CompletedTask;
    }   
    
    // this should be ignored it is not an interface
    [MessageBusSubscription("invalid", QualityOfService.AtMostOnce)]
    public Task Handle(bool notAnInterfaceImplementation)
    {
        return Task.CompletedTask;
    }
}

Ответы [ 2 ]

1 голос
/ 03 августа 2020

Вы можете использовать Type.GetInterfaceMap, чтобы сделать что-то вроде этого:

var type = typeof(TestTopicNotificationHandler);
foreach (var implementedInterface in type.GetInterfaces())
{
    if (!implementedInterface.IsGenericType
        || implementedInterface.GetGenericTypeDefinition() != typeof(ITopicNotificationHandler<>))
        continue;
    
    var interfaceMap = type.GetInterfaceMap(implementedInterface);  
    foreach (var implementedMethod in interfaceMap.TargetMethods)
    {
        var attribute = implementedMethod.GetCustomAttribute<MessageBusSubscriptionAttribute>();
        if (attribute == null)
            continue;
        
        Console.WriteLine($"{implementedMethod.Name}: {attribute.Path}");
    }
}

Мы находим все ITopicNotificationHandler интерфейсы, которые реализует этот тип. Для каждого из них мы получаем отображение, которое сопоставляет методы, определенные в интерфейсе, с соответствующими методами, определенными в типе. Мы l oop через каждый из соответствующих методов, определенных для типа, и смотрим на атрибуты для каждого.

Рабочий пример

0 голосов
/ 03 августа 2020

Я хочу избежать поиска по имени функции - Почему это необходимо?

В любом случае, вот решение, которое находит все методы с именем Handle, которые имеют подписку MessageBusSubscription attribute:

var allMethods = typeof(TestTopicNotificationHandler).GetMethods();
var handleMethods = allMethods.Where(x=>x.Name=="Handle");
foreach(var method in handleMethods)
{
    var attr = method.GetCustomAttributes(typeof(MessageBusSubscription));
    if(attr.Any())
    {
       // Here you have the method with the attribute. 
    }
}

Это должно быть довольно легко адаптировать, чтобы также искать методы, определенные в интерфейсе, и игнорировать их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...