Click here to Skip to main content
Click here to Skip to main content

LINQing the Reflection

, 15 Sep 2009
Rate this:
Please Sign up or sign in to vote.
Using LINQ with reflection with minimum coding to access the members dynamically

Introduction

Using Reflection at runtime is a bit complex and accessing objects by iterating through Collection takes time. I tried to use LINQ to object to simplify this process as much as possible.

In the sample given here, I explain two scenarios of using Reflection:

  1. Dynamically getting the count of Property of specific Type in an object
  2. Dynamically loading an overloaded method

The illustration in the code has both classic methods and methods using LINQ.

Using the Code

I'm going to use the below object to demonstrate the logic.

A simple object is used here for simplicity of code.

Object consists of nine properties and two methods overloaded into the objects:

public class person 
{
    public string name { get; set; } 
    public string Address { get; set; }
    public string URL { get; set; } 
    public string City { get; set; }
    public int pincode { get; set; } 
    public int Age { get; set; } 
    public int Height { get; set; }
    public DateTime DOB { get; set; }
    public string street { get; set; }

public string myMethod(int i)
    {
    return "This invoke method with single Parameter";
    }

public string myMethod(int i, string j)
    {
    return "This invoke method with double Parameter";
    }
}

The requirement here is to display the count of string attributes for object dynamically.

Initially, reflection is used to achieve this by iterating through the Propertyinfo collection.

private static int StringMemeberCountClassic<T>(this T source) where T : class 
    { 
        //use Propertyinfo collection to get the Count of String Member 
        int iret; iret = 0; PropertyInfo[] oProp = source.GetType().GetProperties(); 
        foreach (PropertyInfo prop in oProp) 
            { 
                if (prop.PropertyType.Name == "String") 
                    { iret++; } 
            } 
        return iret;
     }

This works fine, but I feel this code can be improved to an extent.

I thought of using LINQ to object query to reduce the looping and create method. I also created another method that will return the count of attributes not of type string.

     /// Extension Method to Count number of String Member .
private static int StringMemeberCount<t>(this T source) where T : class 
    { 
    //use LINQ to get the Count of String Member 
    int iret = (from a in source.GetType().GetProperties() 
             where a.PropertyType.Name == "String" 
             select a).Count(); 
    return iret; 
    } 
    /// <summary>/// Extension Method to Count number of non String Member. 
  private static int nonStringMemeberCount<t>(this T source) where T : class
     { 
    //use LINQ to get the Count of String Member 
        int iret = (from a in source.GetType().GetProperties() 
        where a.PropertyType.Name != "String" 
        select a).Count(); 
        return iret;
     }

Secondly, there is a requirement to load the method dynamically. I used a custom way of doing this as shown below. When the code is executed, it throws an exception as ambiguous match found. Unfortunately this was an overloaded method:

private static string overloadCallClassic<T>(T source, int param) where T : class 
{
MethodInfo mi = source.GetType().GetMethod("myMethod");
if (param == 1)
 { 
    object[] arguments = { 1 }; 
    return mi.Invoke(source, arguments).ToString();
  }
if (param == 2)
  { 
     object[] arguments = { 1, "abz" }; 
    return mi.Invoke(source, arguments).ToString();
  }
return ""; 
}

To fix this issue, I rewrote the code using LINQ as follows:

private static string overloadCall<t>(  T source,int param) where T : class
{
    MethodInfo mi = (from a in source.GetType().GetMethods()
                     where a.Name == "myMethod" && a.GetParameters().Length ==
                     param 
                     select a).FirstOrDefault();
    if (param == 1) 
    { 
        object[] arguments = { 1 };
        return mi.Invoke(source, arguments).ToString();
    }
    if (param == 2) 
    {
        object[] arguments = { 1, "abz" };
        return mi.Invoke(source, arguments).ToString(); 
    }

    return "";          
}

This works fine as expected and can be loaded dynamically.

I created the following sample program to check all the above mentioned implementations:

static class Program
{
static void Main(string[] args)
{
    person P = new person();
    DateTime start = DateTime.Now;
    Console.WriteLine("Start Classic Load: {0}", start);
    System.Console.WriteLine(
        "No of String Member in Classic way without linq Person Object : " +
        P.StringMemeberCount().ToString());
    DateTime stop = DateTime.Now;
    Console.WriteLine("Stop Classic Load: {0}", stop.Date.Millisecond);
    Console.WriteLine("Elapsed Time: {0}", stop - start);
    start = DateTime.Now;
    Console.WriteLine("Start Linq Method : {0}", start);
    System.Console.WriteLine("No of String Member in Person Object : " +
        P.StringMemeberCount().ToString());
    stop = DateTime.Now;
    Console.WriteLine("Stop Linq Method : {0}", stop);
    Console.WriteLine("Elapsed Time: {0}", stop - start);

    System.Console.WriteLine("No of Non-String Member in Person Object : " +
       P.nonStringMemeberCount().ToString());
    ///Calling Over loaded Methods ...
    try
    {
        System.Console.WriteLine("Calling overloaded Method with one parameter : " +
            overloadCallClassic(P, 1));
    }
    catch (Exception e)
    {
        System.Console.WriteLine("Calling overloaded Exception : " + e.Message );
    }

    System.Console.WriteLine("Calling overloaded Method with one parameter : " +
        overloadCall(P,1));
    System.Console.WriteLine("Calling overloaded Method with 2 parameters : " +
        overloadCall(P,2));
     System.Console.ReadKey();
}

When the project is compiled and executed, the result will be:

Points of Interest

This will run on Visual Studio 2008 and .NET 3.5.

This is how I relished the power of LINQ to objects to access the Collection object with ease and in an effective way.

This really helped me in reducing my lines of code to a greater extent and gave better performance. Smile | :)

Here I have used Extension methods which is another interesting feature of C# 3.0.

History

  • 15th September, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Appusamy.subbian
Software Developer (Senior)
India India
No Biography provided
Follow on   Twitter

Comments and Discussions

 
QuestionCan it support MySql Pinmemberfangyuan312322-Apr-12 17:28 
Questionfaster LINQ? PinmemberMilos Tomic21-Sep-09 20:21 
AnswerRe: faster LINQ? Pinmemberkarunappu21-Sep-09 20:48 
GeneralMy vote of 2 PinmemberMelionu15-Sep-09 20:42 
GeneralRe: My vote of 2 PinmemberKirill Kovalev16-Sep-09 9:38 
GeneralMy vote of 4 PinmemberLee Humphries16-Sep-09 10:55 
Melionu wrote:
nothing special

Correct, plus some of the English is a little off, however it's a well structured short introductory article suitable for beginners that explains things as it goes. In other words a classic CP article.
What articles have you written lately?
 
I just love Koalas - they go great with Bacon.

GeneralRe: My vote of 4 Pinmemberkarunappu16-Sep-09 14:44 
GeneralRe: My vote of 4 PinmemberLee Humphries16-Sep-09 16:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140709.1 | Last Updated 15 Sep 2009
Article Copyright 2009 by Appusamy.subbian
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid