Sunday, November 25, 2007 10:56 PM mehfuzh

How to control C# interface behavior using attribute.

Attribute based programming , is the most cool thing in C#, you can give some extra behavior to a method or interface , along with method call parameters.

Moving forward, let's say we are doing a service call , and we need to define the external method , right from the interface.

Now, here is an interface

public interface IFlickr : IDisposable
{
 // photo releated method.
 [FlickrMethod("flickr.photos.getInfo")] 
 Photo GetPhotoDetail(string id, PhotoSize size);
....
....
....
}

As, you can see I have defined the rest method to be called along with method declaration.To make this happen, on the start of every interface implementation we need to add, for example, in LINQ.Flickr project , inside the DataAccess that implements IFlickr, looks like

Photo IFlickr.GetPhotoDetail(string id, PhotoSize size)
{
....
....
    string method = Helper.GetExternalMethodName();
....
....
....
}

As, we can see that the actual magic goes to a Helper class that will extract the attribute value from the interface. Basically, on each method call, the execution of the extraction code is bit costly. Therefore, the best solution is to parse the attributes for interface when DataAccess class is initialized and store it in a key value pair dictionary.

Therefore, Inside the .ctor call of DataAccess. let's add the following lines.

public DataAccess()
{
    try
    {
         .....
         .....

          Helper.RefreshExternalMethodList(typeof(IFlickr));
    }
    catch (Exception ex)
    {
        throw new ApplicationException(ex.Message);      
    }
}

Lets, step in to RefreshExternalMethodList and we will get

private static IDictionary<string, string> _methodList = new Dictionary<string, string>();

internal static void RefreshExternalMethodList(Type interfaceType)
{
    // not yet initialized.
    if (_methodList.Count == 0)
    {
        MethodInfo[] mInfos = interfaceType.GetMethods();

        foreach (MethodInfo mInfo in mInfos)
        {
            if (mInfo != null)
            {
                object[] customArrtibute = mInfo.GetCustomAttributes(typeof(FlickrMethodAttribute), true);

                if (customArrtibute != null && customArrtibute.Length == 1)
                {
                    FlickrMethodAttribute mAtrribute = customArrtibute[0] as FlickrMethodAttribute;

                    string methodFullName = mInfo.ReflectedType.FullName + "." + mInfo.Name;

                    if (!_methodList.ContainsKey(methodFullName))
                    {
                        _methodList.Add(methodFullName, mAtrribute.MethodName);
                    }
                }
            }
        }

    }
}

Which does, nothing but maps the Interface method to external method. Therefore, going back to GetExternalMethodName() , all it does is, it takes the interface ref from the current stacktrace and passes the name to return the name of the external method. That looks like

private static object _lockHandler = new object();

internal static string GetExternalMethodName()
{
    lock (_lockHandler)
    {
        StackTrace trace = new StackTrace(1, true);
        MethodBase methodBase = trace.GetFrames()[0].GetMethod();
        return _methodList[methodBase.Name];
    }
}

Note, that StackTrace is started from 1st frame,that means , it gets frame list starting from last method, which is, the IFlickr implementation in DataAccess.

Did I miss anything, yep happy holidays and thanksgiving :-)

kick it on DotNetKicks.com Filed under:

Comments

# How to define interface behavior using attribute..

Sunday, November 25, 2007 11:58 AM by DotNetKicks.com

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# re: How to control C# interface behavior using attribute.

Tuesday, November 27, 2007 4:31 AM by Gernot

Sorry, but your example has nothing to do with AOP. AOP is a way to add functionality that is executed before or after method calls. If you know rails, before_filter and after_filter is AOP.  

# re: How to control C# interface behavior using attribute.

Friday, November 30, 2007 10:33 PM by mehfuzh

Yes, you are right about AOP, the example is basically way of attribute base programming sample, i have removed the "AOP" word from the top of my article.

Any suggestions are most welcome :-)

# 本周链接列表(2007.11.26-2007.12.02)

Saturday, December 01, 2007 8:57 PM by Anders Cui

本期链接列表的主要内容有:ASP.NET MVC Framework, MVP, 设计模式, Python, 英语学习 :)

# 本周链接列表(2007.11.26-2007.12.02)

Saturday, December 01, 2007 9:06 PM by Anders Cui

本期链接列表的主要内容有:ASP.NET MVC Framework, MVP, 设计模式, Python, 英语学习 :)

# re: How to control C# interface behavior using attribute.

Friday, December 07, 2007 10:11 AM by Shafqat Ahmed

Nice post. Don't think you that you need to do a "lock (_lockHandler)" when you try to get the parent method name. On a multithreaded environment it may cause wait time becuase of locks. Since the stacktrace is a private variable with method scope only, you will not need to make it explicitly threadsafe ... it is thread safe by default.

# re: How to control C# interface behavior using attribute.

Friday, December 07, 2007 12:32 PM by mehfuzh

Good catch, although the lock is not for the private  StackPanel , it is for shared static variable "_methodList[methodBase.Name]", but as it is readonly, lock is not needed at all , anyway.

Thanks for the comment!

Leave a Comment

(required) 
(required) 
(optional)
(required)