Пользовательские атрибуты в C # - PullRequest
2 голосов
/ 16 сентября 2009

У меня есть свой атрибут для моей страницы, например:

[PageDefinition("My page", "~/Parts/MyPage.aspx")]

Мой PageDefinition выглядит следующим образом, где AttributeItemDefinitions устанавливается для Title, Url, IsPage и IsUserControl

public class PageDefinition : AttributeItemDefinitions
{
    public PageDefinition(string title, string url)
        : this()
    {
        Title = title;
        Url = Url;
    }

    public PageDefinition()
    {
        IsPage = true;
        IsUserControl = false;
    }
}

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

Ответы [ 2 ]

1 голос
/ 16 сентября 2009

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

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

Для настройки этой платформы IoC мне нужно вызвать члена определенного класса и сказать ему, какой класс существует для отображения интерфейса.

  ioc.ConfigureMapping(classType, interfaceType)

Чтобы найти все эти сопоставления, я использую следующие два метода в одном из моих вспомогательных классов

 internal static void Configure(IoCContainer ioc, Assembly assembly)
 {
     foreach (var type in assembly.GetTypes())
          AddToIoCIfHasComponentAttribute(type, ioc);
 }

 internal static void AddToIoCIfHasComponentAttribute(Type type, IoC ioc)
 {
     foreach (ComponentAttribute att in type.GetCustomAttributes(typeof(ComponentAttribute), false))
     {
          ioc.ConfigureMapping(attribute.InterfaceType, type);
     }
 }

То, что я делаю здесь, перечисляет все типы сборок в первом методе, а затем вычисляет атрибут во втором.

Вернуться к вашей проблеме:

Используя подобный подход, вы можете найти все отмеченные классы и записать их в контейнер (ArrayList или аналогичный) вместе со всеми данными, которые вы определили в атрибуте (путь к странице и т. Д.).

Обновление (Ответ на комментарий)

Когда вы создаете свою программу в Visual Studio, у вас обычно есть один или несколько проектов. Для каждого проекта вы получите отдельную сборку (файл .dll или .exe). Приведенный выше код будет проверять все классы в пределах одной сборки. Таким образом, сборка представляет собой набор собранных файлов .cs. Таким образом, вы хотите искать сборку, а не каталог файлов .cs (которые являются исходным кодом и не являются частью запущенного приложения.)

Так что, вероятно, не хватает: как вы можете получить доступ к сборке из вашего кода, когда вы хотите искать классы? Вы просто берете ЛЮБОЙ известный вам класс (который находится в сборке / проекте, где находятся другие ваши классы) и получаете сборку, в которой он находится, вызывая

var assembly = typeof(MyDummyClass).Assembly;

и после этого вы будете вызывать что-то, полученное из кода выше

AnalyzeClasses(assembly)

и AnalyzeClasses будут выглядеть как

 internal static void AnalyzeClasses(Assembly assembly)
 {
     foreach (var type in assembly.GetTypes())
          AnalzyeSingleClass(type);
 }

 internal static void AnalzyeSingleClass(Type type)
 {
     foreach (MyCustomAttribute att in type.GetCustomAttributes(typeof(MyCustomAttribute), false))
     {
          Console.WriteLine("Found MyCustomAttribute with property {0} on class {1}",
                  att.MyCustomAttributeProperty,
                  type);
     }
 }

И вы просто позвоните, прежде чем запустить код приложения, например, прямо вверху в main () (для приложений) или если сложно в продвинутом, вы также можете звоните по требованию, когда вам нужны собранные данные. (Например, со страницы ASP.NET)

0 голосов
/ 16 сентября 2009

Это может быть больше, чем нужно, но ...

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

http://www.codeproject.com/KB/architecture/RuntimeTypeLoader.aspx

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