Category Archives: .NET

Forcing Derived type to apply custom attribute

Introduction

This article illustrates options to force attributes on derived types.

Background

In .NET eco system, Attributes are not inheritable. This means any attribute applied on base class are not applied/inherited on derived class. This article looks at different options available to forcer the attributes on derived types at compile time and at run time.

Approach

There are two approaches (with different intensions)

1. Forcing at run time : The base class constructor code will check for the presence of attribute and throw error runtime if attribute is not changed.

2. Forcing at compile time: Using ObsoleteAttribute, the Mandatory attribute will be reflected at compile time and will raise the error. This information is taken from this question on Stackoverflow.com

Using the Code

Forcing attribute at run time

  1. Creating a Custom Attribute
    class CustomAttribute : System.Attribute { }  
  2. In the constructor of base check the attribute
     publicBase() { CheckCustomAttribute(); } 
  3. If class type is base, skip the attribute check
     if (!(this.GetType() == typeof(Base))) 
  4. If class is derived type, check whether attribute exists or not.
    var attr = System.Attribute.GetCustomAttributes(
                             this.GetType())
                            .SingleOrDefault(t => typeof(CustomAttribute)
                            .IsAssignableFrom(t.GetType()));
    
  5. The IsAssignableFrom take care of any attribute that derives from CustomAttribute.

  6. Throw error is attribute does not exist.
    if (attr == null)
     {
         throw new Exception(String.Format(
                             "Derived class {0} doesnot apply {1} attribute",
                             this.GetType().Name,
                             typeof(CustomAttribute).Name));
     }

Forcing attribute at compile time

There is a special attribute ObsoleteAttribute. It is sealed so cannot be subclassed. The C# compiler has special handling for this attribute.

However to use Obsolete attribute rather awkwardly, It can be applied to a custom attribute. Then applying that custom attribute (on class/structs) will force compiler to show error

  1. Create a custom attribute
    public class MandatoryAttribute : Attribute{}
    
  2. Decorate the custom attribute with ObsoleteAttribute
    [Obsolete("MandatoryAttribute is required", true)]
    public class MandatoryAttribute : Attribute{}
    

     

  3. Apply Custom attribute to class/member to get notification (as compile time error) on any type
    //[MandatoryAttribute]
    public class Base
    {
     //[MandatoryAttribute]
     public void SayHello() {}
    }
    

Uncommenting MandatoryAttribute raises awkard compile time error.

This is awkawrd because the error message is like

“MandatoryAttribute’ is obsolete: ‘MandatoryAttribute is required’    <filename>    <projectname>’”

Download source code from src link for this post.

Advertisements

Fast CSV Row Count using Binary Reader

Introduction

The code snippet in this article illustrates an efficient/fast row/line count algorithm using BinaryReader API.

Background

CSV file format has text data. There is no official restriction on number of rows, number of columns or file size. 

RFC4180 Format

Due to no restriction, to read number of lines, complete file reading is required.

Using the code

In windows operating system Line break is represented by CR LF \r \n .

The basic approach is to read all the content through streaming, and find for the Line breaks.

BinaryReader API is used for stream read. This class  reads primitive data types as binary values in a specific encoding.

private static int GetLineCount(string fileName)
{
    using (FileStream fs = File.OpenRead(fileName))
    using (BinaryReader reader = new BinaryReader(fs))
    {
       int lineCount = 0;

       char lastChar = reader.ReadChar();
       char newChar = new char();

      do
      {
        newChar = reader.ReadChar();
        if (lastChar == '\r' &amp;&amp; newChar == '\n')
        {
          lineCount++;
        }
        lastChar = newChar;
      } while (reader.PeekChar() != -1);
      return lineCount;
}

Alternatives:

  1. Read all records at a time, and calculate the Array Length using File.ReadAllLines API. This is good for small files. For large files (>2GB) OutOfMemoryException is expected.
  2. StreamReader API: There are 2 options
    1. using ReadLine function to read lines. This has trade-off of line to string conversion which is not needed.
    2. using Read() and Peek() method. This is similar to using BinaryReader approach but these methods return integer and not char so little bit more logic is required for character comparisons.

Points of Interest

Below are some efficient CSV parsers I have come across/used.

  1. TextFieldParser : This is built-in .NET structured text file parser. This parser is placed in Microsoft.VisualBasic.dll library.
  2. KBCsv library: This is efficient, easy to use library developed by Kent Boogaart.