2

I'm working on an app that will read in data from my database, do some processing, and then export the results out to a fixed width flat file.

I'm starting out with the code in this question, and building off that.

Now, there are three main data types for the exported file, String, Num, and Decimal(x,y); where x are the numbers to the left of the decimal point and y is the numbers to the right.

I have this so far as my custom attribute:

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

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

Is it possible to create a custom attribute (or some other structure) that I can use to build properties like this:

[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; }
Community
  • 1
  • 1
Jim B
  • 8,344
  • 10
  • 49
  • 77
  • Looks like `FixedWidthColumn` takes two args yet you're passing in three in your example – dtsg Aug 10 '12 at 15:54
  • Yeah; it's pseudo code; just trying to give an example of what i'd like the final output to be similar to – Jim B Aug 10 '12 at 15:57

4 Answers4

2

You could extend FixedWidthColumnAttribute to carry the parameter type property.

       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;
             }


         }  

usage:

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

         [FixedWidthColumn(5, 6, FixedWidthColumnType.Decimal, Digits = 3, FractionalDigits = 4)]
alexm
  • 6,854
  • 20
  • 24
2

First, you should rename your class name FixedWithColumn as FixedWithColumnAttribute. Maybe, it's just a convention; but i think that is required in order to apply with C# semantics. Second, you should indicate typeof(Type) in the calling attribute declaration :

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

Third, declare constructor like that:

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

I hope it can help you

user1587368
  • 314
  • 2
  • 6
  • It *is* just a convention, and C# and other .NET languages will allow other names (obviously the C# rule that if it doesn't cause an ambiguity you are allowed to leave out the "Attribute" at the end of the name, doesn't apply to those without an "Attribute" at the end of the name). It's still a very good idea to follow such conventions. – Jon Hanna Aug 10 '12 at 16:02
  • So with this example, how would i tell it the number of fractional digits to include for a decimal type? – Jim B Aug 10 '12 at 16:47
  • You can pass a derived instance of NumberFormatInfo into the parameter of the attribute class and you set the CurrencyDecimalDigits with the appropiate value – user1587368 Aug 10 '12 at 18:34
1

To answer the specific question: no you can not have an attribute within an attribute.

Attributes can only take a limited range of data types in their constructors. See MSDN documentation for examples. So you can't have an attribute that exposes a class as a property.

Rob Walker
  • 46,588
  • 15
  • 99
  • 136
0

I would recommend using inheritance, for example:

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

In your examination code, you can grab all of the FixedWidthColumnAttribute objects, allowing inheritance, then examine the type (using GetType) to determine exactly what kind of object it is.

Guvante
  • 18,775
  • 1
  • 33
  • 64