Деревья выражений c динамическим параметром
Я хочу преобразовать это:
Func<dynamic, object> myFunc = t => return t.Name + " " + t.Surname;
в дерево выражений.
вот что я придумал:
ParameterExpression target = ExpressionParameter(typeof(dynamic), "target");
ParameterExpression result = ExpressionParameter(typeof(object), "result");
BlockExpression block = Expression.Block(
new [] { result },
Expression.Assign(
result,
Expression.Add(
Expression.Add(
Expression.Property(target, "Name"),
Expression.Constant(" ", typeof(string))
),
Expression.Property(target, "Surname")
)
)
);
Func<dynamic, object> myFunc = Expression.Lambda<dynamic, object>>(block, target).Compile();
однако компилятору не нравится typeof(dynamic) и я тебя понимаю. dynamic - это не тип, это object в сущности.
поэтому я продолжил изменять ParameterExpression:
ParameterExpression target = ExpressionParameter(typeof(object), "target");
теперь код компилируется, но есть проблема во время выполнения.
Я пытаюсь получить значение собственность Name of target, который может иметь смысл, если объект был dynamic.
но поскольку target считается типа object, выражение выдает ошибку, сообщая мне Name не существует как свойство.
есть ли выражение для извлечения динамического свойства?
1 ответов
для тех, кто заинтересован или был заинтересован в решении:
ParameterExpression target = Expression.Parameter(typeof(object), "target");
ParameterExpression result = Expression.Parameter(typeof(object), "result");
CallSiteBinder getName = Binder.GetMember(
CSharpBinderFlags.None, "Name", typeof(Program),
new CSharpArgumentInfo[] {
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}
);
CallSiteBinder getSurname= Binder.GetMember(
CSharpBinderFlags.None, "Surname", typeof(Program),
new CSharpArgumentInfo[] {
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}
);
BlockExpression block = Expression.Block(
new[] { result },
Expression.Assign(
result,
Expression.Call(typeof(string).GetMethod("Concat", new Type[] { typeof(object[]) }),
Expression.NewArrayInit(typeof(object),
Expression.Dynamic(getName, typeof(object), target),
Expression.Constant(" ", typeof(object)),
Expression.Dynamic(getSurname, typeof(object), target)
)
)
)
);
Func<dynamic, object> myFunc = Expression.Lambda<Func<dynamic, object>>(block, target).Compile();
вот именно то, что я делаю:
- создал
CallSiteBinderкоторый получает значение динамического свойстваNameдинамического объекта, переданного в качестве аргумента - создал
CallSiteBinderкоторый получает значение динамического свойстваSurnameдинамического объекта, переданного в качестве аргумента - вызывается метод
string.Concat(params object[] args). Для этого мне нужно отправить свои аргументы как массивobject. Я создаю массив со значениямиgetName," "иgetSurname.
я использовал следующий ответ в качестве руководства и ссылки:
C# 4 "динамический" в деревьях выражений
с вышеуказанным подходом можно было бы сделать что-то вроде этого:
dynamic person = new ExpandoObject();
person.Name = "Matt";
person.Surname = "Smith";
object value = myFunc(person);
Console.WriteLine(value); //Will print out "Matt Smith"
//Internally it just calls:
//string.Concat(new object[] { person.Name, " ", person.Surname });