2

I have a generic class like below:

public class MyClass<T, TProperty>
{
     MyClass(Expression<Func<T, TProperty>> expression)
     {
     }
}

In my case, I want to dynamically create an instance of that class using Activator. So what I need is to create an expression for the constructor. What I have are the types (System.Type) and an object (System.Object) and I want something like below:

Expression<Func<T, TProperty>> exp = x => someValue;

"someValue" is declared as object but it's real type is definitely TProperty. It's resolved by reflection so the type here is object.

The problem is that the type T and TProperty will be generic, I don't know the types until run-time so I can't cast "someValue" to TProperty. What we have are typeof(T), typeof(TProperty) and an object -,-

Ani
  • 111,048
  • 26
  • 262
  • 307
Van Thoai Nguyen
  • 986
  • 9
  • 22
  • 2
    It isn't clear what constructor or property code you want to invoke; if this was regular c# (not expression), what would the outcome be? – Marc Gravell Dec 03 '11 at 10:13
  • Thank Marc. I want to instantiate an object of type MyClass, because the constructor needs the expression so what I need to to have is somehow dynamically create an expression as I described. – Van Thoai Nguyen Dec 03 '11 at 10:25
  • Here is a trick that I always use. Create a small library and write the type safe version of what you want to do, compile it, and open the .dll in Reflector. When you select ".NET 2.0" in View / Options / Optimization, you'll see what `Expression` objects the C# compiler has generated on your behalf. – Steven Dec 03 '11 at 10:30
  • @Thoai you can also use NewExpression to do this directly rather than using Activator. In not at a PC right now, but let me know if you want me to do an example later – Marc Gravell Dec 03 '11 at 12:03
  • @Marc: I don't think that's relevant here since the `MyClass` instance is not going to be "newed up" inside an expression. The expression is actually required to return a reference to an existing object. – Ani Dec 03 '11 at 13:19

1 Answers1

4

Ok, I think I understand the question.

Given sample input:

Type typeOfT = typeof(int);
Type typeOfTProperty = typeof(string);
object someValue = "Test";

You want to create code equivalent to:

var myClassInstance = new MyClass<int, string>(t => "Test");

Here's how you can do that.

First, create the expression-tree:

var parameter = Expression.Parameter(typeOfT, "t");
var body = Expression.Constant(someValue, typeOfTProperty);

// Will automatically be an Expression<Func<T, TProperty>> without any extra effort.
var lambda = Expression.Lambda(body, parameter);

And then use reflection to create the MyClass<T, TProperty> instance:

var myClassType = typeof(MyClass<,>).MakeGenericType(typeOfT, typeOfTProperty);

//  Make the MyClass<,> constructor public first...
var myClassInstance = Activator.CreateInstance(myClassType, lambda);
Ani
  • 111,048
  • 26
  • 262
  • 307