Как добавить видимую информацию в классы C # с помощью атрибутов? - PullRequest
3 голосов
/ 01 февраля 2012

Я пытаюсь добавить информацию в интерфейс C # и пытаюсь добавить эту информацию, используя атрибуты.

Скажем, например, что у меня везде есть параметры int, и некоторые из этих параметров int являются "идентификаторы строк ", а некоторые являются" идентификаторами столбцов ".Я хотел бы иметь возможность сделать это:

namespace RowIdTest1
{
    using System;

    public class Class1
    {
        public int Get([RowId] int r, [ColumnId] int c) { return 3; }
        public void Set([RowId] int r, [ColumnId] int c, int x) { return; }
    }

    [AttributeUsageAttribute(AttributeTargets.All)]
    public class RowIdAttribute : System.Attribute { }

    [AttributeUsageAttribute(AttributeTargets.All)]
    public class ColumnIdAttribute : System.Attribute { }
}

, чтобы, когда другой программист использовал мою DLL и просматривал Class1 в Visual Studio, он или она увидит это в «Class1 (из метаданных)»"window:

namespace RowIdTest1
{
    public class Class1
    {
        public Class1();

        public int Get([RowId] int r, [ColumnID] int c);
        public void Set([RowId] int r, [ColumnID] int c, int x);
    }
}

Когда я пытаюсь это сделать, атрибуты вообще не отображаются.

Я знаю, что вы можете делать такие вещи с ///-comments.

Я знаю, что вы можете использовать класс System.ComponentModel.DescriptionAttribute для чего угодно (хотя описания методов будут появляться, а описания параметров не будут появляться).

Я делаю что-то совершенно странное с атрибутами C #?Не подходит?Безумный

Ответы [ 5 ]

6 голосов
/ 01 февраля 2012

Я делаю что-то странное с атрибутами C #?

Да.

Вы пытаетесь использовать атрибут для выражения бизнес-домена факт о параметре.Это не то, для чего нужны атрибуты.Атрибуты предназначены для выражения фактов о механизме языка программирования .То есть, когда вы говорите:

[Obsolete]
class BlackAndWhiteTelevision {}

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

То, что конкретный параметр представляет идентификатор строки, являетсяФакт о бизнесе вашего метода, а не о механизме метода.Вы должны поместить атрибуты в параметры метода, которые выражают такие вещи, как «этот параметр имеет значение по умолчанию» или «этот параметр должен быть упорядочен по значению при вызове через COM-взаимодействие» или «этот параметр будет записан до того, как он будет считан из»- это факты о параметре как переменной в языке программирования , а не факты о том, как параметр моделирует некоторую концепцию в вашем бизнес-процессе .

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

http://blogs.msdn.com/b/ericlippert/archive/2009/02/02/properties-vs-attributes.aspx

4 голосов
/ 01 февраля 2012

Я делаю что-то странное с атрибутами C #?Не подходит?Безумный?

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

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

public int Get(int rowId, int columnId)

Соедините это с /// комментариями, как вы упомянули, и у вас есть довольно эффективный способ рассказать потребителям вашего класса, каковы ваши ожидания.

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

public struct RowId {
    private int _rowId;
    public int Value{get{return _rowId;}}
    public RowId(int rowId) {_rowId = rowId;}
}


public int Get(RowId rowId, ColumnId columnId)

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

3 голосов
/ 01 февраля 2012

Нет, вы не можете. Почему бы просто не назвать аргументы

public int Get(int rowId, int columnId)

1 голос
/ 01 февраля 2012

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

0 голосов
/ 01 февраля 2012

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

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