Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Saturday, May 2, 2015

C# Building a Dictionary in Attributes

Introduction

The last blog I did about .NET attributes was to add a simple attribute to an existing method. This entry is about building a "Dictionary" of data into a set of attributes on a method. For example, I want the attributes to document each parameter of a method. So what I want is something that looks like this:


[Method(Description="This is the fibonacci sequence"
       ,Parameters={ {"in", "The input parameter" } })]
int Fibonacci(int in)
{
    if (in == 0 || in == 1) return 1;
    return Fibonacci(in - 2) + Fibonacci(in - 1);
}

Keep in mind this is NOT valid syntax in .NET (at least I don't think it is).

Attribute Definition

The above description won't work- only because I don't think that C# allows parameter definitions with complex objects as values. However, I found a solution that is pretty good at [1]. The partial solution is to separate each element that would be in the dictionary into a unique attribute. The attribute I put together looks like this:
                                                                                                        
[AttributeUsage(AttributeTargets.All,AllowMultiple=true)]
public class SomeParameter : Attribute
{
     private string m_name;
     private string m_description;

     public string Name 
     {
         get
         {
             return m_name;
         }
         set
         {
             m_name = value;
         }
     }


     public string Description
     {
         get
         {
             return m_description;
         }
         set
         {
             m_description = value;
         }
     }
}

I put one of the critical sections in bold. The trick is to set the AllowMultiple flag to true, which lets us actually add more than one of these attributes to the method [2]. To use this:

[SomeParameter(Name="input1",Description="The input to fib.")]
public int Fibonacci(int input1)
{
}

Note: Remember to put the public in front of the method! If it is not listed as public, it will not show up when using the reflection method I'm going to show below. This isn't a very good example since fibonacci only takes one parameter. However if I add a new method:


[SomeParameter(Name="parm1",Description="The first input to Calculate2.")]
[SomeParameter(Name="parm2",Description="The second input to Calculate2.")]
public int Calculate2(int parm1, int parm2)
{
}

Why do this? The reason I want to do this is to add a way to query more information about parameters and functions. Here is my complete program to illustrate how the multiple parameters can also be queried:

using System;


[AttributeUsage(AttributeTargets.All)]
public class SomeMethod : Attribute
{
    private string m_description;

    public string Description
    {

        get
        {
            return m_description;
        }

        set
        {
            m_description = value;
        }
    }
}


[AttributeUsage(AttributeTargets.All,AllowMultiple=true)]
public class SomeParameter : Attribute
{
    private string m_name;
    private string m_description;

    public string Name
    {
        get
        {
            return m_name;
        }

        set
        {
            m_name = value;
        }
    }


    public string Description
    {
        get
        {
            return m_description;
        }

        set
        {
            m_description = value;
        }
    }


}


public class HelloWorld
{
    HelloWorld()
    {
    }


    [SomeMethod(Description="Sample calculation")]
    [SomeParameter(Name="parm1", Description="Parameter #1")]
    [SomeParameter(Name="parm2", Description="Parameter #2")]
    public int Calculate2(int parm1, int parm2)

    {
        return parm1 + parm2;
    }


    static public void Main()
    {
        HelloWorld h = new HelloWorld();

        int output = h.Calculate2(4, 5);


        Type hwInfo = typeof(HelloWorld);

        System.Reflection.MemberInfo[] memberInfo = hwInfo.GetMembers();
        foreach(System.Reflection.MemberInfo mInfo in memberInfo)
        {
            Console.WriteLine(mInfo.ToString());

            object[] attributes = mInfo.GetCustomAttributes(true);
            Console.WriteLine("\tNumber of attributes: " + attributes.Length);
            for(int i=0; i<attributes.Length; i++)
            {
                System.Console.WriteLine("\t\t" + attributes[i]);
            }
        }
    }
}

This program goes through and prints out all of the methods available in the C# class.


REFERENCES

[1] - http://stackoverflow.com/questions/21265431/how-can-i-accept-a-dictionary-of-data-as-a-custom-net-attribute-parameter

[2] - https://msdn.microsoft.com/en-us/library/tw5zxet9.aspx


Sunday, March 8, 2015

C# .NET Attributes Data (Beginner's Guide)

Introduction

This guide is all about how to add metadata to a C# program. This entry is aimed at the beginning C# developer who has experience with other programming languages. Metadata has a variety of uses- at the company I work for we're going to use it to provide more verbose information to consumers of some given code. It's a very .NET-y solution to a problem we've already solved in C++ using parsers. The advantage to metadata is that it's a solution that is already supported by the .NET framework.

Please note that all of the code that I'm writing is compiled using Mono. Mono is a cross-platform tool that can compile C# code into an intermediate form which can then be run.

The Initial Program

For the initial program I decided to use the "Hello World" program provided by the Mono project [1]. This had the duel purpose of testing out my Mono installation. The original HW program was kind of simple for the type of meta-information I wanted to provide. So it was modified. Here is the original code (once again, credit to the mono project):

using System;

public class HelloWorld
{
    static public void Main()
    {
        Console.WriteLine("Hello Mono World!");
    }
}

Let's change the program to instantiate a HelloWorld object and use a method to print a message out.

using System;

public class HelloWorld
{
    public void PrintMsg(String msg)
    {
        Console.WriteLine(msg);
    }

    static public void Main()
    {
        HelloWorld hw = new HelloWorld();
        hw.PrintMsg("Hello World!");
    }
}

Adding an Attribute Class

The example class now has a basic method (PrintMsg). I want to start inserting special meta data to the class and some of its functions. Let's start with a simple description field. To achieve this a custom Attribute class must be written. I'm going to call the attribute class "SomeMethod":

using System;

[AttributeUsage(AttributeTargets.All)]
public class SomeMethod : Attribute
{
    private string m_description;

    public string Description
    {
        get
        {
            return m_description;
        }
        set 
        {
            m_description = value;
        }
    }
}

This is a really simple attributes class that has one property called "Description". The Description property is implemented with the get/set methods. These are just shorthand ways to implement these basic accessors. It's also much more formal than most other languages.

The top line contains [AttributeUsage(AttributeTargets.All)] seems to help declare this class as an attribute that can be applied using metadata calls [2].

Applying the Custom Attribute

To apply the custom attribute, all that is necessary is to apply some metadata before the method and it automatically gets attached:

using System;

[AttributeUsage(AttributeTargets.All)]
public class SomeMethod : Attribute
{
    private string m_description;

    public string Description
    {
        get
        {
            return m_description;
        }
        set 
        {
            m_description = value;
        }
    }
}


public class HelloWorld
{
    [SomeMethod(Description="This is a description of PrintMsg")]
    public void PrintMsg(String msg)
    {
        Console.WriteLine(msg);
    }

    static public void Main()
    {
        HelloWorld hw = new HelloWorld();
        hw.PrintMsg("Hello World!");
    }
}

I put the introduced attribute in bold.

Using Reflection to Query Attributes

The only step left is now querying the attributes placed on members/methods. This is pretty simple using a language feature called Reflection. So I modified the main part of the program to contain the following lines:

public class HelloWorld
{
    [SomeMethod(Description="This is a description of PrintMsg")]
    public void PrintMsg(String msg)
    {
        Console.WriteLine(msg);
    }

    static public void Main()
    {
        HelloWorld hw = new HelloWorld();
        hw.PrintMsg("Hello World!");

        Type hwInfo = typeof(HelloWorld);

        System.Reflection.MemberInfo[] memberInfo = hwInfo.GetMembers();
        foreach(System.Reflection.MemberInfo mInfo in memberInfo)
        {
            Console.WriteLine(mInfo.ToString());
       
            object[] attributes = mInfo.GetCustomAttributes(true);
            Console.WriteLine("\tNumber of attributes: " + attributes.Length);
            for(int i=0; i<attributes.Length; i++)
            {
                System.Console.WriteLine("\t\t" + attributes[i]);
            }
        }
    }
}

This program is now modified to print out all of the methods inside of HelloWorld and whether or not there were custom attributes applied. The point of this step is to partially explore what can be queried with Reflection.

Learning Note: When I ran this program in Mono it was observed that my one simple class had more than one method. Being a veteran C++ developer I am familiar with methods (constructors, assignment operators, etc) being added to classes. It appears as though C# also does something similar adding: 

  • Boolean Equals(System.String)
  • Int32 GetHashCode()
  • System.Type GetType()
  • System.String ToString()
  • Void .ctor()
I must admit that these methods all look really useful! As a C# beginner I think another entry might be useful to describe what these methods do. 


If we want to detect when a method has an attribute, it's as simple as:

public class HelloWorld
{
    [SomeMethod(Description="This is a description of PrintMsg")]
    public void PrintMsg(String msg)
    {
        Console.WriteLine(msg);
    }

    static public void Main()
    {
        HelloWorld hw = new HelloWorld();
        hw.PrintMsg("Hello World!");

        Type hwInfo = typeof(HelloWorld);

        System.Reflection.MemberInfo[] memberInfo = hwInfo.GetMembers();
        foreach(System.Reflection.MemberInfo mInfo in memberInfo)
        {
            Console.WriteLine(mInfo.ToString());

            SomeMethod sm = 
               (SomeMethod) Attribute.GetCustomAttribute( mInfo
                                                        , typeof(SomeMethod));
            if (sm != null)
            {
                Console.WriteLine("\tHAS IT!\n");
            }
        }
    }
}

This program will now print out a message when the SomeMethod is obtained!

Conclusion

I really hate to admit this- C# looks awesome! I really enjoyed using Mono to run these examples. I know the examples were simple but I'm impressed with how the language defines its own custom attributes. In my next entry on this feature I'll explore how to add lists of things to attributes.


REFERENCES

[1] - http://www.mono-project.com/docs/getting-started/mono-basics/

[2] - https://msdn.microsoft.com/en-us/library/aa288454%28v=vs.71%29.aspx

[3] -https://msdn.microsoft.com/en-us/library/aa288454%28v=vs.71%29.aspx#vcwlkattributestutorialanchor3