Как вы помещаете Func в атрибут С# (аннотация)?
У меня есть аннотация С#, которая:
[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]) };
}
У меня нет ошибок в классе Annotation, но когда дело доходит до регенерации всего решения, каждый раз, когда я объявляю метод с аннотацией, у меня есть ошибка, которая говорит мне, что я должен использовать литералы в аннотации.
Я понимаю, что есть ограничения, но есть ли способ избежать этой проблемы? Я знаю, что могу использовать строку вместо Func и динамически искать функцию, имя которой совпадает с строкой, но я бы не хотел этого делать.
Спасибо за помощь:)
Ответы
Ответ 1
Я не думаю, что это возможно, С# позволяет вам использовать атрибуты только с постоянными значениями.
Один из способов сделать это - создать класс вместо func, а затем передать тип этого класса в атрибут.
Затем вам необходимо создать экземпляр с отражением и выполнить в нем метод.
Итак, примером может быть:
public interface IDoStuff
{
IList<string> Execute();
}
тогда ваш атрибут возьмет тип вместо Func
public OperationInfo(VisibilityType v, string title, Type type)
{
///...
}
тогда вы создадите класс, который реализует ваш интерфейс и передает его в атрибут. Хотя это будет означать, что (по крайней мере, изначально и не зная вашей проблемы), вам нужно будет создать новый класс каждый раз, когда вы захотите вернуть разные результаты.
Ответ 2
Из спецификации С#:
17.1.3 Типы параметров атрибутов
Типы позиционных и именованных параметров для класса атрибута ограничены типами атрибутных параметров, которые:
. Один из следующих типов: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
. Объект типа.
. Тип System.Type.
. Тип перечисления, если он имеет общедоступную доступность, и типы, в которых он вложен (если есть), также имеют общедоступную доступность (§17.2).
. Одномерные массивы вышеуказанных типов.