1

以前の質問で、プロパティ名を取得するためのLinq式と拡張メソッドで、式と拡張を使用した2つの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);
    }    
}

上記に関する私の質問は次のとおりです。

  • Bindを呼び出すと、2番目のパラメーターは現在のクラスのメンバーであるため、x.Bind(Name => Id);のようなものになります。x.Bind(Name => y.Id)の代わりに。この場合、destinationExpression.ExpressionはMemberExpressionではなくConstantExpressionであるため、バインドは失敗します。その場合に機能させるために何を変更する必要があるのか​​わかりません。

  • x.Bind(Na123me => Id)のように、プロパティ名が正しくない場合にコンパイル時に失敗させる方法はありますか?

4

1 に答える 1

0

いいえ。実際には、このような表現を簡単に作成できるようにするためのトリックを使用しているだけです。ただし、ラムダ式がコンパイル時に特定のパターンに従うように強制する方法はありません。そのため、LINQ to Entitiesのようなテクノロジでは、多くの実行時例外が発生する傾向があります。

于 2011-03-31T20:09:19.500 に答える