Могу ли я иметь атрибут внутри атрибута?

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

Я начинаю с кода в этом вопросе и строю его.

Теперь существует три основных типа данных для экспортируемого файла: String, Num и Decimal(x,y); где x - числа слева от десятичной точки, а y - числа справа.

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

public class FixedWidthColumn : Attribute
{
    public int Position { get; set; }
    public int Length { get; set; }

    public FixedWidthColumn(int position, int length)
    {
        Position = position;
        Length = length;
    }
}

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

[FixedWidthColumn(3,2, String)]
public string CompanyId

[FixedWidthColumn(6, 20, Num)]
public int Sku { get; set; }

[FixedWidthColumn(5, 10, Decimal(6,4)]
public decimal Price { get; set; }

4 ответа

Решение

Вы можете расширить FixedWidthColumnAttribute для переноса свойства типа параметра.

       public enum FixedWidthColumnType 
       {
            String,
            Num,
            Decimal 
       }

        [AttributeUsage(AttributeTargets.Property)]
        public class FixedWidthColumnAttribute : Attribute  
        {      
             public int Position { get; private set; }      
             public int Length { get; private set; }        
             public int Digits {get;set;}
             public int FractionalDigits {get;set}

             public FixedWidthColumnType Type {get; private set;}
             public FixedWidthColumn(int position, int length, 
                   FixedWidthColumnType type)

             {          this.Position = position;          
                        this.Length = length;      
                        this.Type = type;
             }


         }  

использование:

         [FixedWidthColumn(4, 10, FixedWidthColumnType.String)]

         [FixedWidthColumn(5, 6, FixedWidthColumnType.Decimal, Digits = 3, FractionalDigits = 4)]

Во-первых, вы должны переименовать имя вашего класса FixedWithColumn в FixedWithColumnAttribute. Может быть, это просто соглашение; но я думаю, что это необходимо для применения с семантикой C#. Во-вторых, вы должны указать typeof(Type) в объявлении атрибута вызова:

[FixedWidthColumn(3,2,typeof(String))]

В-третьих, объявите конструктор так:

public FixedWidthColumnAttribute(int position, int length, Type objType)

Я надеюсь, что это может помочь вам

Чтобы ответить на конкретный вопрос: нет, вы не можете иметь атрибут в атрибуте.

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

Я бы порекомендовал использовать наследование, например:

public class FixedWidthDecimalAttribute : FixedWidthColumnAttribute
...
public FixedWidthDecimal(int position, int wholeDigits, int fractionalDigits)
...
[FixedWidthDecimal(5, 6, 4)]

В коде экзамена вы можете получить все FixedWidthColumnAttribute объекты, разрешающие наследование, затем исследуют тип (используя GetType) точно определить, что это за объект.

Другие вопросы по тегам