4
votes

Let's say I have the following methods:

public static String GetString(int a) {
    return "";
}

public static int GetInt(int a) {
    return 0;
}

Now I want to create a lambda expression to one of these methods where I only know the following in compile time:

MethodInfo methodInfo; The method info of one of the above methods.

PropertyType propertyType; The property type of the return type of one of the above methods.

What I cannot use here is a generic type, since I don't know which method I wish to call in compile time.

Scenario:

I have the following model class:

public class Model {
    public String Name {
        get;set;
    }

    public int Number {
        get;set;
    }
}

In runtime I wish to inject information to this model.

public static void Inject<T>(T model) {
    foreach(PropertyInfo propertyInfo in typeof(T).GetProperties()) {
        Func<int, object> funcGet = GetValueFunc(propertyInfo.PropertyType);
        propertyInfo.SetValue(model, funcGet.Invoke(0));
    }
}

public static Func<int, object> GetValueFunc(Type propertyType) {
    MethodInfo methodInfo = // say I know the method info here mapped to the propertyType

    // this won't work since object isn't of either int or String
    var iParam = Expression.Parameter(typeof(int), "iParam");
    var call = Expression.Call(methodInfo, iParam);
    var lambda = Expression.Lambda<Func<int, object>>(call, iParam);
    return lambda.Compile();
}

Is there a way of actually doing this?

I know that you can do Expression.Convert(Expression.Parameter(typeof(object), "o"), propertyType); if you don't know the type of an parameter in runtime. Is there a similar way of doing it for return types?

2
Only sadness and grief lie down that road. Abandon ye quest and repent! - Martijn

2 Answers

2
votes

Well, you're not exactly casting the 'return type', as your not modifying the existing method code. You need to instead cast the result of that method's call, and that's perfectly doable, pretty much using what you've stated:

var call = Expression.Call(methodInfo, iParam);
var cast = Expression.Convert(call, typeof (Object));
var lambda = Expression.Lambda<Func<int, Object>>(cast, iParam);
0
votes

I think that this resolve your problem too

    public static Func<int, object> GetValueFunc(Type propertyType)
    {
        MethodInfo methodInfo = // say I know the method info here mapped to the propertyType

        Func<int, object> result = (arg) => methodInfo.Invoke(null, new object[] {arg});
        return result;
    }