Как поместить Func в атрибут C # (аннотация)? - PullRequest
20 голосов
/ 11 декабря 2011

У меня есть аннотация C #, которая:

[AttributeUsage(AttributeTargets.Method)]
public class OperationInfo : System.Attribute {
    public enum VisibilityType {
        GLOBAL,
        LOCAL,
        PRIVATE
    }
    public VisibilityType Visibility { get; set; }
    public string Title { get; set; }
    public Func<List<string>, List<string>> Func;

    public OperationInfo(VisibilityType visibility, string title, Func<List<string>, List<string>> function) {
        Visibility = visibility;
        Title = title;
        Func = function;
    }
}

Как видите, есть свойство Func, и я хочу, чтобы оно вызывалось динамически. По сути, я хотел бы проанализировать все методы, которые имеют эту аннотацию, а затем вызвать Func, связанный с аннотацией.

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

[OperationInfo(OperationInfo.VisibilityType.GLOBAL, "echo", IDoEcho)]
    public static string DoEcho(string a)
    {
        return a;
    }

    [OperationInfo(OperationInfo.VisibilityType.PRIVATE, null, null)]
    public static List<string> IDoEcho(List<string> param) {
        return new List<string>() { DoEcho(param[0]) };
    }

У меня нет ошибок в моем классе аннотаций, но когда дело доходит до восстановления всего решения, каждый раз, когда я объявляю метод с аннотацией, у меня появляется ошибка, которая говорит мне, что я должен использовать литералы в аннотации.

Я понимаю, что есть ограничения, но есть ли способ избежать этой проблемы? Я знаю, что могу использовать строку вместо Func и динамически искать функцию, имя которой совпадает со строкой, но я бы не хотел этого делать.

Спасибо за помощь:)

Ответы [ 2 ]

9 голосов
/ 11 декабря 2011

Из спецификации C #:

17.1.3 Типы параметров атрибута

Типы позиционных и именованных параметров для класса атрибута ограничены типами параметров атрибута, которые:

· Один из следующих типов: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.

· Тип объекта.

· Тип System.Type.

· Тип enum при условии, что он имеет общедоступную доступность, и типы, в которые он вложен (если есть), также имеют общедоступную доступность (§17.2)..

· одномерные массивы указанных типов.

7 голосов
/ 11 декабря 2011

Я не думаю, что это возможно, c # позволяет вам использовать только атрибуты с постоянными значениями.

Один из способов сделать это - создать класс вместо func, а затем передать тип этого класса в атрибут. Затем вам нужно будет создать его экземпляр с помощью отражения и выполнить в нем метод.

Итак, пример будет:

public interface IDoStuff
{
    IList<string> Execute();
}

тогда ваш атрибут будет иметь тип вместо Func

public OperationInfo(VisibilityType v, string title, Type type)
{
   ///...
}

Затем вы создадите класс, который реализует ваш интерфейс, и передадите его в атрибут. Хотя это будет означать, что (по крайней мере на начальном этапе и без знания вашей проблемы) вам нужно будет создавать новый класс каждый раз, когда вы захотите вернуть разные результаты.

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