C# Reflection Code to Search Objects for Fields Properties and Methods and Get Values

2016-07-06

Code below will search for a given named property, field, or method inside a given object.

It will search in below order:

  1. Properties
  2. Fields
  3. Methods

It will continue to search until it finds a match that holds or returns (for methods) a non-null value.

E.g. If you searched for “Name” and if there is a property called Name that returns null then the code will continue looking for fields and methods.

SearchTillNotNull  Parameter

If you set the parameter SearchTillNotNull to false then the method will return as soon as it finds a hit even if the resolved value is null.

Searching for methods

Code searches for a method with either the same name as the given SearchFor or a method name with “Get” and SearchFor phrase. (e.g. if SearchFor=”Name” then a methods “GetName”, “getName”, and “Name” will all qualify).

Parameters for methods

Code will only execute matching methods if either the method doesn’t require any parameters or the number of parameters given to the code is same as the number of parameters required by the particular method.

Notes:

  • All searches are are case insensitive and uses OrdinalIgnoreCase string comparison.
  • Uses reflection
  • Implemented in C#.Net
  • Tested to work on .Net framework 2.0 and above

Below is the code, you can also download the .cs file from here


using System;

namespace CMRSoft.Reflection
{
 class ObjectReader
 {
 /// <summary>
 /// Searches the given object until it finds a value for the given SearchFor string
 /// </summary>
 /// <param name="Obj">Object to search inside</param>
 /// <param name="SearchFor">Name of the value to look for</param>
 /// <param name="SearchTillNotNull">If set to true, will continue searching if it finds a match but received null value from the match</param>
 /// <returns>Found value or null</returns>
 public object GetValueFromObject(object Obj, string SearchFor, bool SearchTillNotNull = true, params object[] MethodParameters)
 {
    var t = Obj.GetType();

    // check all properties
    foreach (var prop in t.GetProperties())
    {
       if (prop.Name.Equals(SearchFor, StringComparison.OrdinalIgnoreCase))
       {
          var tmp = prop.GetValue(Obj, null);
          if (tmp != null || !SearchTillNotNull)
          {
             return tmp;
          }
       }
    }


    // check all fields
    foreach (var fld in t.GetFields())
    {
       if (fld.Name.Equals(SearchFor, StringComparison.OrdinalIgnoreCase))
       {
          var tmp = fld.GetValue(Obj);
          if (tmp != null || !SearchTillNotNull)
          {
             return tmp;
          }
       }
    }


    // search methods
    foreach (var mtd in t.GetMethods())
    {
       if (mtd.Name.Equals(SearchFor, StringComparison.OrdinalIgnoreCase) || mtd.Name.Equals("get" + SearchFor, StringComparison.OrdinalIgnoreCase))
       {
          var parameters = mtd.GetParameters();
          if (parameters.Length == 0 || (MethodParameters != null && parameters.Length == MethodParameters.Length))
          {
             var tmp = mtd.Invoke(Obj, MethodParameters);
             if (tmp != null || !SearchTillNotNull)
             {
                return tmp;
             }
          }
       }
    }

    return null;
    }
   }
}

Example use:

namespace CMRSoft.Reflection
{
class Program
{
   static void Main(string[] args)
   {
      ObjectReader _r = new ObjectReader();

      var testObj = new Test() { Value1 = 100, Value2=3 };

      Console.WriteLine(_r.GetValueFromObject(testObj, "value1"));
      // outputs 100

      Console.WriteLine(_r.GetValueFromObject(testObj, "pi", MethodParameters: 4)); 
      // Notice the search phrase does not contain "get". The Object Reader looks for methods with get prefix to what's being searched for.
      // outputs 3.1416

      Console.ReadLine();
   }
}

class Test : ITest
{
   public double Value1 { get; set; }
   public double Value2 { get; set; }

   public double getPi(int DecimalPlaces)
   {
      return Math.Round(Math.PI, DecimalPlaces);
   }
}

interface ITest
{
   double getPi(int DecimalPlaces);
}
}

Please feel free to comment your suggestions.

Menol

This entry was posted in C#.Net and tagged , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *