Проверка имени свойства во время компиляции в лямбда-выражении - PullRequest
1 голос
/ 01 апреля 2011

В моем предыдущем вопросе Выражения Linq и методы расширения для получения имени свойства Я спросил о привязке данных между двумя свойствами POCO с использованием выражений и расширений. Я получил полезный ответ, и он работает нормально, но у меня есть вопрос по этому поводу.

Вот код:

public static class Extensions
{
    public static void Bind<TSourceProperty, TDestinationProperty>(this INotifyPropertyChanged source, Expression<Func<TSourceProperty, TDestinationProperty>> bindExpression)
    {
        var expressionDetails = GetExpressionDetails<TSourceProperty, TDestinationProperty>(bindExpression);
        var sourcePropertyName = expressionDetails.Item1;
        var destinationObject = expressionDetails.Item2;
        var destinationPropertyName = expressionDetails.Item3;

        // Do binding here
        Console.WriteLine("{0} {1}", sourcePropertyName, destinationPropertyName);
    }

    private static Tuple<string, INotifyPropertyChanged, string> GetExpressionDetails<TSourceProperty, TDestinationProperty>(Expression<Func<TSourceProperty, TDestinationProperty>> bindExpression)
    {
        var lambda = (LambdaExpression)bindExpression;

        ParameterExpression sourceExpression = lambda.Parameters.FirstOrDefault();
        MemberExpression destinationExpression = (MemberExpression)lambda.Body;

        var memberExpression = destinationExpression.Expression as MemberExpression;
        var constantExpression = memberExpression.Expression as ConstantExpression;
        var fieldInfo = memberExpression.Member as FieldInfo;
        var destinationObject = fieldInfo.GetValue(constantExpression.Value) as INotifyPropertyChanged;

        return new Tuple<string, INotifyPropertyChanged, string>(sourceExpression.Name, destinationObject, destinationExpression.Member.Name);
    }
}

Использование:

public class TestSource : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Name { get; set; }        
}

public class TestDestination : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Id { get; set; }    
}

class Program
{        
    static void Main(string[] args)
    {
        var x = new TestSource();
        var y = new TestDestination();

        x.Bind<string, string>(Name => y.Id);
    }    
}

Мои вопросы относительно вышеизложенного:

  • Когда я звоню Бинду, Второй параметр является членом текущий класс, так что у меня есть кое-что как x.Bind (Имя => Я бы); вместо x.Bind (Name => y.Id). В этом случае, Привязка терпит неудачу, так как destinationExpression.Expression является ConstantExpression вместо MemberExpression. Я не уверен что Мне нужно изменить, чтобы сделать это работать в таком случае.

  • Есть ли способ заставить его выйти из строя во время компиляции, если имя свойства неверно, например, x.Bind (Na123me => Id)?

1 Ответ

0 голосов
/ 01 апреля 2011

Нет. Дело в том, что вы просто используете трюк, чтобы упростить создание такого выражения. Но нет способа обеспечить, чтобы лямбда-выражение следовало определенному шаблону во время компиляции. Вот почему такие технологии, как LINQ to Entities, имеют тенденцию вызывать множество исключений во время выполнения.

...