2

I have some code snippet given as below:

Want to resolve this conditation by checking the type at runtime.

PropertyInfo pi = type.GetProperty("propertyName");

var expression = new Object(); // this give me error after expression runs!

    // Want to resolve this conditation by checking the type at runtime.
    if (pi.PropertyType == typeof(DateTime))
            {
               // Want to pass the generic type parameter which has a same type created at runtime by identifying the property type.
                expression = BuildExpression<T, DateTime>(data, group.Member);
            }

private Func<T, V> BuildExpression<T, V>(IEnumerable<T> items, string propertyName)
    {
      Type type = typeof(T);
      PropertyInfo pi = type.GetProperty(propertyName);
      Type PropertyType = pi.DeclaringType;
      var parameter = Expression.Parameter(typeof(T), propertyName);
      var cast = Expression.TypeAs(parameter, pi.DeclaringType);
      var getterBody = Expression.Property(cast, pi);
      var exp = Expression.Lambda<Func<T, V>>(getterBody, parameter);
      return exp.Compile();
    }

Problem: I have to write condition on type I have to check the type of property by reflection and then have to build the expression.

What I want: I want to check the runtime time the Type of property and want to build runtime Generic parameter of that type which is same as a property type.

Basically I want to remove the If condition on type checking and What I want is, the code should automatically detect the property type and pass the same type in Generic parameter argument, so that I don't have to check with all the types with If condition. Like for string, decimal, double etc..

Could you please do let me know that resolution as I want to check the property type at runtime and want to create Generic parameter type with the same type as property has.

Cœur
  • 37,241
  • 25
  • 195
  • 267
nunu
  • 3,184
  • 10
  • 43
  • 58
  • 1
    well, what is your `BuildExpression` method? and could it take a `Type` parameter rather than a `T` generic? – Marc Gravell Nov 06 '12 at 10:38
  • Marc, It's taking generic parameter type. I have added the same method within the question. – nunu Nov 06 '12 at 10:42
  • and what is the type of your `expression` local variable? – Marc Gravell Nov 06 '12 at 10:43
  • That's I am wondering because I am not sure about how would I initialize my local variable because it will be different for different type checking at runtime.. I have posted the code above on my opinion where it should be like it. BUT not sure how to deal with this type of condition... I have initialize with "var expression = new Object();", BUT it gives me error after expression runs! – nunu Nov 06 '12 at 10:44

1 Answers1

1

Having a method that returns Func<T,V> (for object T and member-type V) is problematic, because you can't really do anything useful with that at runtime. You can't assign it to a typed delegate without knowing the T and V at compile time, and using DynamicInvoke is not a great idea. Frankly, you would be better building a Func<object,object>, and just dealing with object at runtime. Reflection and generics do not mix well.

private static Func<object, object> BuildExpression(
    Type type, string propertyName)
{
    var parameter = Expression.Parameter(typeof(object));
    var body = Expression.TypeAs(Expression.PropertyOrField(Expression.TypeAs(
        parameter, type), propertyName), typeof(object));
    return Expression.Lambda<Func<object, object>>(body, parameter).Compile();
}

However, at that point you could, IMO, just switch to a library like FastMember, and use name-based access:

var accessor = TypeAccessor.Create(type);
var obj = ...
var propVal = accessor[obj, propertyName];
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Marc, Thanks for the info. After using your method, I am getting LamdaExpression for . That's fine. Lets assume that, I want to build with 'integer' type lamda expression out of this. How would I convert the result from your method to 'Integer' expression ?? – nunu Nov 06 '12 at 12:49
  • @nunu having it as an "integer expression" causes huge problems, since you can't have a variable that is "an integer expression or a string expression or a datetime expression or ..." - you *can*, however, have "an object expression". What exactly do you want to do? how would you see yourself using it if it was an integer expression? – Marc Gravell Nov 06 '12 at 12:51
  • what I want to do here is, Whatever result (Func) I am getting from your method 'BuildExpression, I want to use that result Func in 'GroupBy' extension method of IEnumerable. E.g. var expResult = BuildExpression(typeof(T), "City"); var gropupedResult = myList.GroupBy(expResult); How would I achieve this? – nunu Nov 06 '12 at 12:59
  • @nunu I wouldn't to start with; I might, however, write a custom `GroupBy(this IEnumerable, string memberName)`, basically borrowing the code from this custom `OrderBy` answer: http://stackoverflow.com/questions/41244/dynamic-linq-orderby/233505#233505 – Marc Gravell Nov 06 '12 at 13:22