using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Dynamic;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
public class ExpressionTreeUtils
{
private static Expression<Func<dynamic, decimal>> CreateLambdaCastExpression()
{
// source
var sourceParameterExpression = Expression.Parameter(typeof(object), "source");
var binder = Binder.GetMember(
CSharpBinderFlags.None, "IntProp", typeof(ExpressionTreeUtils),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
// CSharpBinderFlags.ConvertExplicit: explicit cast
// (will convert double to decimal)
// CSharpBinderFlags.None: implicit cast
// (will convert int to decimal)
var convert = Binder.Convert(CSharpBinderFlags.ConvertExplicit, typeof(decimal), typeof(ExpressionTreeUtils));
// source.sourceProperty
var sourcePropertyExpression = Expression.Dynamic(
binder, typeof(object), sourceParameterExpression);
// (decimal) source;
var castedValueExpression = Expression.Dynamic(
convert, typeof(decimal), sourcePropertyExpression);
// () => (decimal) source;
return Expression.Lambda<Func<dynamic, decimal>>(castedValueExpression,
sourceParameterExpression);
}
public static void Test()
{
dynamic source = new ExpandoObject();
source.IntProp = 1.5;
decimal r = CreateLambdaCastExpression().Compile()(source);
Console.WriteLine(r);
}
}
class Program
{
static void Main(string[] args)
{
ExpressionTreeUtils.Test();
}
}
}
dXNpbmcgTWljcm9zb2Z0LkNTaGFycC5SdW50aW1lQmluZGVyOwp1c2luZyBTeXN0ZW07CnVzaW5nIFN5c3RlbS5EeW5hbWljOwp1c2luZyBTeXN0ZW0uTGlucS5FeHByZXNzaW9uczsKCm5hbWVzcGFjZSBDb25zb2xlQXBwbGljYXRpb24xCnsKICAgIHB1YmxpYyBjbGFzcyBFeHByZXNzaW9uVHJlZVV0aWxzCiAgICB7CiAgICAgICAgcHJpdmF0ZSBzdGF0aWMgRXhwcmVzc2lvbjxGdW5jPGR5bmFtaWMsIGRlY2ltYWw+PiBDcmVhdGVMYW1iZGFDYXN0RXhwcmVzc2lvbigpCiAgICAgICAgewogICAgICAgICAgICAvLyBzb3VyY2UKICAgICAgICAgICAgdmFyIHNvdXJjZVBhcmFtZXRlckV4cHJlc3Npb24gPSBFeHByZXNzaW9uLlBhcmFtZXRlcih0eXBlb2Yob2JqZWN0KSwgInNvdXJjZSIpOwoKICAgICAgICAgICAgdmFyIGJpbmRlciA9IEJpbmRlci5HZXRNZW1iZXIoCiAgICAgICAgICAgICAgICBDU2hhcnBCaW5kZXJGbGFncy5Ob25lLCAiSW50UHJvcCIsIHR5cGVvZihFeHByZXNzaW9uVHJlZVV0aWxzKSwKICAgICAgICAgICAgICAgIG5ld1tdIHsgQ1NoYXJwQXJndW1lbnRJbmZvLkNyZWF0ZShDU2hhcnBBcmd1bWVudEluZm9GbGFncy5Ob25lLCBudWxsKSB9KTsKCiAgICAgICAgICAgIC8vIENTaGFycEJpbmRlckZsYWdzLkNvbnZlcnRFeHBsaWNpdDogZXhwbGljaXQgY2FzdCAKICAgICAgICAgICAgLy8gKHdpbGwgY29udmVydCBkb3VibGUgdG8gZGVjaW1hbCkKICAgICAgICAgICAgLy8gQ1NoYXJwQmluZGVyRmxhZ3MuTm9uZTogaW1wbGljaXQgY2FzdAogICAgICAgICAgICAvLyAod2lsbCBjb252ZXJ0IGludCB0byBkZWNpbWFsKQogICAgICAgICAgICB2YXIgY29udmVydCA9IEJpbmRlci5Db252ZXJ0KENTaGFycEJpbmRlckZsYWdzLkNvbnZlcnRFeHBsaWNpdCwgdHlwZW9mKGRlY2ltYWwpLCB0eXBlb2YoRXhwcmVzc2lvblRyZWVVdGlscykpOwoKICAgICAgICAgICAgLy8gc291cmNlLnNvdXJjZVByb3BlcnR5CiAgICAgICAgICAgIHZhciBzb3VyY2VQcm9wZXJ0eUV4cHJlc3Npb24gPSBFeHByZXNzaW9uLkR5bmFtaWMoCiAgICAgICAgICAgICAgICBiaW5kZXIsIHR5cGVvZihvYmplY3QpLCBzb3VyY2VQYXJhbWV0ZXJFeHByZXNzaW9uKTsKCiAgICAgICAgICAgIC8vIChkZWNpbWFsKSBzb3VyY2U7CiAgICAgICAgICAgIHZhciBjYXN0ZWRWYWx1ZUV4cHJlc3Npb24gPSBFeHByZXNzaW9uLkR5bmFtaWMoCiAgICAgICAgICAgICAgICBjb252ZXJ0LCB0eXBlb2YoZGVjaW1hbCksIHNvdXJjZVByb3BlcnR5RXhwcmVzc2lvbik7CgogICAgICAgICAgICAvLyAoKSA9PiAgKGRlY2ltYWwpIHNvdXJjZTsKICAgICAgICAgICAgcmV0dXJuIEV4cHJlc3Npb24uTGFtYmRhPEZ1bmM8ZHluYW1pYywgZGVjaW1hbD4+KGNhc3RlZFZhbHVlRXhwcmVzc2lvbiwKICAgICAgICAgICAgICAgIHNvdXJjZVBhcmFtZXRlckV4cHJlc3Npb24pOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyB2b2lkIFRlc3QoKQogICAgICAgIHsKICAgICAgICAgICAgZHluYW1pYyBzb3VyY2UgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgICAgICBzb3VyY2UuSW50UHJvcCA9IDEuNTsKICAgICAgICAgICAgZGVjaW1hbCByID0gQ3JlYXRlTGFtYmRhQ2FzdEV4cHJlc3Npb24oKS5Db21waWxlKCkoc291cmNlKTsKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUocik7CiAgICAgICAgfQogICAgfQoKICAgIGNsYXNzIFByb2dyYW0KICAgIHsKICAgICAgICBzdGF0aWMgdm9pZCBNYWluKHN0cmluZ1tdIGFyZ3MpCiAgICAgICAgewogICAgICAgICAgICBFeHByZXNzaW9uVHJlZVV0aWxzLlRlc3QoKTsKICAgICAgICB9CiAgICB9Cn0K