Дерево выражений 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 ожидает строку или другое, не очень полезное для этого параметра проблемы.

0 ответов

Другие вопросы по тегам