Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Параметры атрибутов 
:(
    Опции темы
IRQ
Дата 2.12.2006, 23:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 7.5.2006

Репутация: нет
Всего: нет



Насколько я знаю в атрибутах параметры можно указывать только непосредственно. То есть скажем строковые параметры указываеются литералами. Мы можем написать [DisplayName("ABC")] и нельзя вместо ABC указывать всякие переменные. Можно-ли это как-нибудь обойти? Я пишу программу которая будет локализовываться. И было бы удобно вместо параметра атрибута в явном виде подставлять значние нужное. На нужном языке. Например из ресурсов. Возможно-ли это?
PM MAIL   Вверх
mr.DUDA
Дата 6.12.2006, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Сорри что пропустил такой интересный вопрос. Так вот, ответ: нет smile. Можно лишь прописать в атрибуте константу извне атрибута - например, определённую в том же классе.

Но не всё так плохо. Как известно, атрибуты не просто так объявляются над классами, переменными и т.п. Они ещё и используются где-то (иначе вообще смысла в них не было бы, правда?). Из этого следует замечательная вещь: то что мы не можем хранить в атрибутах вычисляемые значения (строки из ресурсов etc.), ещё не значит что мы не можем получать из атрибутов такие значения!

Расшифрую: атрибут является классом. Мы определяем атрибут как класс-наследник System.Attribute. Атрибут принимает и хранит некие значения:
1) эти значения передаются в атрибут через конструктор или именованные свойства
2) далее они хранятся "as is" в метаданных сборки
3) далее, тот кто хочет получить данные из атрибута, вызывает x.GetCustomAttribute(ля-ля-ля), и получает оттуда требуемые данные, используя один из методов или свойств атрибута

Теперь см. пункт 3: что мешает на этапе обращения к свойству атрибута (например, MyAttribute.SomeText) грузить данные из ресурсов и т.п. ? Всё что требуется для загрузки корректных данных - это инфа, переданная в атрибут и хранимая в метаданных сборки. То есть, к примеру можно передавать в конструктор атрибута идентификатор ресурса, а при обращении к свойству - грузить локализованный ресурс по идентификатору.

Если нужен пример - приведу пример.


--------------------
user posted image
PM MAIL WWW   Вверх
Idsa
Дата 7.12.2006, 02:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 14
Всего: 62



Цитата(mr.DUDA @  6.12.2006,  22:32 Найти цитируемый пост)
Если нужен пример - приведу пример.

Было бы неплохо smile 


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
mr.DUDA
Дата 7.12.2006, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Пример:

Код
using System;
using System.Globalization;
using System.Resources;
using System.Reflection;
using System.Threading;

namespace ConsoleApplication4
{
    /// <summary>
    /// Собственный класс атрибута
    /// </summary>
    class MyStringAttribute : Attribute
    {
        public readonly string ResourceKey;

        public MyStringAttribute(string resourceKey)
        {
            ResourceKey = resourceKey;
        }

        /// <summary>
        /// Возвращает локализованную строку по ключу из ResourceKey.
        /// Используется ресурс Resource1.имя_культуры.resx
        /// </summary>
        public string LocalizedString
        {
            get
            {
                ResourceManager resManager = new ResourceManager("ConsoleApplication4.Resource1", typeof(MyStringAttribute).Assembly);
                return resManager.GetString(ResourceKey, Thread.CurrentThread.CurrentCulture);
            }
        }
    }

    /// <summary>
    /// Пример класса, помеченного нашим атрибутом.
    /// В скобках - значение для MyStringAttribute.ResourceKey
    /// </summary>
    [MyString("KeyInResource1")]
    class ExampleClass
    {
    }


    // тестовое приложение
    // предполагается что в проекте есть Resource1.en.resx и Resource1.ru.resx,
    // и оба файла содержат строковый ресурс с ключом KeyInResource1
    class Program
    {
        static void Main()
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            DumpAttribute();

            Thread.CurrentThread.CurrentCulture = new CultureInfo("ru-RU");
            DumpAttribute();
        }

        /// <summary>
        /// Выводит значение, полученное из атрибута MyStringAttribute над классом ExampleClass
        /// </summary>
        static void DumpAttribute()
        {
            object[] attrs = typeof(ExampleClass).GetCustomAttributes(typeof(MyStringAttribute), false);
            MyStringAttribute attr = (MyStringAttribute)attrs[0];

            Console.WriteLine(attr.LocalizedString);
        }
    }
}


Полностью проект:


Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  ConsoleApplication4.zip 10,40 Kb


--------------------
user posted image
PM MAIL WWW   Вверх
IRQ
Дата 7.12.2006, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 7.5.2006

Репутация: нет
Всего: нет



А можно такой же примерчик для DisplayName? Мне вот нужен этот атрибут и именно его значение надо менять. Это значит надо унаследоваться от DisplayNameAttribute и переопределить нужные методы и свойства?

Это сообщение отредактировал(а) IRQ - 7.12.2006, 14:59
PM MAIL   Вверх
mr.DUDA
Дата 7.12.2006, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



IRQ, всё то же самое только да, надо наследовать атрибут от DisplayNameAttribute и перекрывать св-во DisplayName - благо, оно виртуальное smile


--------------------
user posted image
PM MAIL WWW   Вверх
IRQ
Дата 7.12.2006, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 7.5.2006

Репутация: нет
Всего: нет



А ещё вопрос. Как сделать так чтобы не важно было какая культура. Я просто хочу сделать ресурс. и в нём хранить значения свои. И считывать их оттуда. Без всяких культур.
PM MAIL   Вверх
mr.DUDA
Дата 7.12.2006, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Ну тогда достаточно держать в проекте единственный ресурс.


--------------------
user posted image
PM MAIL WWW   Вверх
IRQ
Дата 7.12.2006, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 7.5.2006

Репутация: нет
Всего: нет



Э. Я не знаю как код переделать smile У меня постоянно исключение вылезает о том, что не найдена культура. У меня вот что

Код

    class MyDisplayName : DisplayNameAttribute
    {
        private string ResourceKey;
        
        public MyDisplayName(string _ResourceKey):base(_ResourceKey)
        {
            ResourceKey = _ResourceKey;
        }

        public override string DisplayName
        {
            get
            {
                ResourceManager resManager = new ResourceManager("MyDisplayName.Resource", typeof(MyDisplayName).Assembly);
                return resManager.GetString(ResourceKey);
            }
        }
    }


У меня есть проект. Файл с классом моего атрибута находится внутри проекта но в отдельном файле. Я никак не могу заставить работать.

Это сообщение отредактировал(а) IRQ - 7.12.2006, 22:48
PM MAIL   Вверх
mr.DUDA
Дата 8.12.2006, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Внимательнее надо быть. 

Код
new ResourceManager("MyDisplayName.Resource"


Не будет работать по следующей причине: строка "MyDisplayName.Resource" должна указывать на полное имя ресурса (.resources) в сборке. Таким именем является namespace проекта плюс полная иерархия директорий внутри проекта, где находится файл ресурса, плюс имя самого файла ресурса (без расширения). То есть к примеру, если проект называется "CoolWindowsApplication", а ресурс Resource1.resx лежит в корневой директории проекта, тогда нужно передавать "CoolWindowsApplication.Resource1". Самый надёжный способ проверить, какое имя имеет каждый ресурс -- открыть скомпилированный exe/dll утилитой Reflector.


--------------------
user posted image
PM MAIL WWW   Вверх
IRQ
Дата 18.8.2007, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 41
Регистрация: 7.5.2006

Репутация: нет
Всего: нет



Сейчас появилась необходимость подключать свой класс атрибута к разным сборкам. То есть хочется для удобства сделать отдельную библиотеку которкую можно подключать к разным сборкам и в них использовать мой атрибут. Как это реализовать? Видимо надо сделать конструктор с дополнительными параметрами. Не только ключ ресурса. Какие именно?
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0874 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.