This is something that I solved using reflection, but would like to see how to do it using expression trees.
I have a generic function:
private void DoSo
MethodInfo.MakeGenericMethod
Then just create a delegate and call it. (not in an expression, of course ;p)
Update:
Generally, I prefer to use generic types for this, Activator.CreateInstance
just requires less work. All depends on your situation though.
Yes, it can be done via expression trees. The advantage is that you get a delegate so repeated calls will be far faster than doing MethodInfo.Invoke()
over and over again. The dynamic
keyword can do this also.
Example:
What type would you like to use?
decimal
Selected type 'System.Decimal'
Input Value:
5.47
<<<USING object>>>
The object has static type 'System.Object', dynamic type 'System.Decimal', and value '5.47'
<<<USING dynamic>>>
The object has static type 'System.Decimal', dynamic type 'System.Decimal', and value '5.47'
<<<USING reflection>>>
The object has static type 'System.Decimal', dynamic type 'System.Decimal', and value '5.47'
<<<USING expression tree>>>
The object has static type 'System.Decimal', dynamic type 'System.Decimal', and value '5.47'
Code:
using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace SO2433436
{
class Program
{
static void LogObject<T>(T t)
{
Console.WriteLine("The object has static type '" + typeof(T).FullName + "', dynamic type '" + t.GetType() + "', and value '" + t.ToString() + "'");
}
static void Main(string[] args)
{
Console.WriteLine("What type would you like to use?");
string typeName = Console.ReadLine();
Type userType;
switch (typeName)
{
case "byte": userType = typeof(byte); break;
case "sbyte": userType = typeof(sbyte); break;
case "ushort": userType = typeof(ushort); break;
case "short": userType = typeof(short); break;
case "uint": userType = typeof(uint); break;
case "int": userType = typeof(int); break;
case "string": userType = typeof(string); break;
case "decimal": userType = typeof(decimal); break;
default:
userType = Type.GetType(typeName);
break;
}
Console.WriteLine("Selected type '" + userType.ToString() + "'");
Console.WriteLine("Input Value:");
string val = Console.ReadLine();
object o = TypeDescriptor.GetConverter(userType).ConvertFrom(val);
Console.WriteLine("<<<USING object>>>");
LogObject(o);
Console.WriteLine("<<<USING dynamic>>>");
LogObject((dynamic)o);
Console.WriteLine("<<<USING reflection>>>");
Action<object> f = LogObject<object>;
MethodInfo logger = f.Method.GetGenericMethodDefinition().MakeGenericMethod(userType);
logger.Invoke(null, new[] { o });
Console.WriteLine("<<<USING expression tree>>>");
var p = new[] { Expression.Parameter(typeof(object)) };
Expression<Action<object>> e =
Expression.Lambda<Action<object>>(
Expression.Call(null,
logger,
Expression.Convert(p[0], userType)
)
, p);
Action<object> a = e.Compile();
a(o);
}
}
}