Дерево выражений ArrayAccess не извлекает фактическое свойство
Цель, приложение ниже пытается вызвать различные методы, передавая MemberExpression (фактическое значение свойства во время выполнения).
Сложность заключается в том, что во время разработки в зависимости от некоторых условий будет зависеть, какие свойства будут использоваться, поэтому его можно использовать не так просто, как передать Expression.Property(экземпляр "IKnowWhichPropertyWillBeUsedInAdvance").
Проблема, как упомянуто выше, у меня нет возможности передавать Expression.Property напрямую, поэтому выбранный подход состоял в том, чтобы создать коллекцию объектов Expression.Property и получить доступ к тем, которые используют Expression.ArrayAccess, у реального приложения есть цикл внутри блока, Счетчик может использоваться для доступа к соответствующему свойству, однако, используя последний подход, он возвращает Expression.Property, но не его фактическое значение свойства из экземпляра, который обычно был бы в случае, если Expression.Property был бы передан напрямую. Приведенный ниже код является очень упрощенной версией проблемы, которая, как мы надеемся, должна объяснить ее более четко:
class Program
{
static void Main()
{
var instance = Expression.Parameter(typeof(TestObj));
var methodCall = typeof(Program).GetMethod("TestMethod", new[] { typeof(string) });
var result = Expression.Parameter(typeof(bool));
var param = Expression.Property(instance, "Column1");
var paramCollection = new Expression[1];
paramCollection[0] = param;
var block = Expression.Block(
new[] { result },
Expression.Assign(result, Expression.Constant(false)),
Expression.IfThen(
//passing param directly works fine
//Expression.Equal(Expression.Call(methodCall, param), Expression.Constant(true)),
//however, the below throws exception as the method expects a string but ArrayAccess returns MemberExpression..
Expression.Equal(Expression.Call(methodCall, Expression.ArrayAccess(Expression.Constant(paramCollection), Expression.Constant(0))), Expression.Constant(true)),
Expression.Assign(result, Expression.Constant(true))
),
result
);
Expression<Func<TestObj, bool>> func = Expression.Lambda<Func<TestObj, bool>>(block, new ParameterExpression[] { instance });
Console.WriteLine(func.Compile()(new TestObj()));
Console.ReadKey();
}
class TestObj
{
public string Column1 { get; } = "Column1Value";
}
public static bool TestMethod(string val)
{
return true;
}
}
Вопрос: есть ли способ передать фактическое значение свойства в Expression.Call, не зная, какое именно свойство передается во время разработки? Например, приведенный выше код имеет "Column1" в качестве одного из примеров имени свойства, но в реальном приложении будет х число таких свойств, например "Column2", "Column3" и так далее. Другим подходом может быть Expression.Property(экземпляр, XXX), и для XXX передать ArrayAccessor, который извлечет соответствующее имя свойства, но метод Expression.Property ожидает строку или другое, не очень полезное для этого параметра проблемы.