15

Ok。したがって、データに特定のことが起こったときにコントロールに特定のことを行うために、winFormの特定のコントロールをオブジェクトの特定のプロパティにマップするコードがいくつかあります。すべてうまくいき、うまく機能します。問題ありません。問題は、マッピングにアイテムを追加するために、次のような関数を呼び出すことです。

this.AddMapping(this.myControl,myObject,"myObjectPropertyName");

私が遭遇した問題は、コンパイル時に、上記の行と以下の行の違いを区別するのが非常に難しいことです。

this.AddMapping(this.myControl,myObject,"myObjectPropretyName");

最後のパラメータは文字列であるため、コンパイル時のチェックなど、文字列自体が指定されたオブジェクトの有効なプロパティ名に実際に対応していることを強制するようなものはありません。さらに、リファクタリングや「すべての参照の検索」などは、この種の参照を見逃しているため、プロパティ自体の名前が変更されたときに陽気になります。ですから、私が疑問に思っているのは、渡すものが何らかの方法でプロパティ名を表す文字列になるように関数を変更する方法があるかどうかですが、コンパイル時に実際の値をチェックします。誰かが私に言った式ツリーでこれを行うことができますが、私はそれらを読んだので、接続が表示されないようです。私は次のようなことをしたいです:

this.AddMapping(this.myControl,myObject,myObject.myObjectPropertyName);

あるいは

this.AddMapping(this.myControl,myObject.myObjectPropertyName);

甘いだろう!

何か案は?

4

6 に答える 6

15

3.5 では、式はメンバー名をコードとして指定する 1 つの方法です。あなたが持つことができます:

public void AddMapping<TObj,TValue>(Control myControl, TObj myObject,
       Expression<Func<TObj, TValue>> mapping) {...}

次に、式ツリーを解析して値を取得します。少し非効率的ですが、それほど悪くはありません。

コード例は次のとおりです。

    public void AddMapping<TSource, TValue>(
        Control control,
        TSource source,
        Expression<Func<TSource, TValue>> mapping)
    {
        if (mapping.Body.NodeType != ExpressionType.MemberAccess)
        {
            throw new InvalidOperationException();
        }
        MemberExpression me = (MemberExpression)mapping.Body;
        if (me.Expression != mapping.Parameters[0])
        {
            throw new InvalidOperationException();
        }
        string name = me.Member.Name;
        // TODO: do something with "control", "source" and "name",
        // maybe also using "me.Member"
    }

で呼び出されます:

    AddMapping(myControl, foo, f => f.Bar);
于 2009-04-27T20:48:05.810 に答える
3

Expressionベースのlamda回避策を簡単にするために、拡張メソッドとして記述しました。

  public static string GetPropertyName<T>(this object o, Expression<Func<T>> property)
    {
        var propertyInfo = (property.Body as MemberExpression).Member as PropertyInfo;
        if (propertyInfo == null)
            throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
        var propertyName = propertyInfo.Name;
        return propertyName;
    }

このように電話してください

    class testclass
    {
        public string s { get; set; }
        public string s2 { get; set; }
        public int i { get; set; }

    }

    [TestMethod]
    public void TestMethod2()
    {
        testclass x = new testclass();
        string nameOfPropertyS = this.GetPropertyName(() => x.s);
        Assert.AreEqual("s", nameOfPropertyS);

        string nameOfPropertyI = x.GetPropertyName(() => x.i);
        Assert.AreEqual("i", nameOfPropertyI);

    }

さて、拡張メソッドとして使用することは、実際には別のクラスのプロパティのために1つのクラスでメソッドを呼び出すことができるので、本当に便利です。きっと改善できると思います。

于 2012-10-26T14:47:54.387 に答える
2

次のいずれかを使用して、ラムダを使用することを検討してくださいSystem.Linq.Expressions

extern void AddMapping<T,U>(Control control, T target, Func<T,U> mapping);
extern void AddMapping<T,U>(Control control, T target, Expression<Func<T,U>> mapping);

次に、それを呼び出します

this.AddMapping(this.myControl, myObject, (x => x.PropertyName));

実行時に抽象構文ツリーを分解する必要がある場合は、 Expression 引数を使用して、プロパティ名を文字列として取得するなどの反射的なことを行います。または、デリゲートに必要なデータを釣り上げる作業を任せます。

于 2009-04-27T20:53:29.447 に答える
1

プロパティ名として文字列リテラルを渡すべきではありません。代わりに、を使用する必要がありますYourClass.PROPERTY_NAME_FOO

これらの文字列は、クラスで const として宣言する必要があります。

public const String PROPERTY_NAME_FOO = "any string, it really doesn't matter";
public const String PROPERTY_NAME_BAR = "some other name, it really doesn't matter";

または、文字列についてはまったく気にする必要はなく、プロパティ名だけを気にする必要があります。

public const int PROPERTY_NAME_FOO = 0;
public const int PROPERTY_NAME_BAR = 1; //values don't matter, as long as they are unique

これにより、有効なプロパティを参照しない文字列が関数呼び出しに入るのを防ぐことができます。

Intelisense は、オート コンプリートの候補として、クラス内のプロパティ名を表示できます。

于 2009-04-27T20:47:28.510 に答える
1

あなたが探しているのは、静的反射と呼ばれるものです。恥知らずなプラグイン => http://emiajnet.blogspot.com/2009/05/getting-fun-with-net-static-reflection.html そして、こちらのはるかに優れた記事: http://www.lostechies.com/blogs/ガブリエルシェンカー/アーカイブ/2009/02/03/動的反射対静的反射.aspx

于 2009-09-09T17:18:44.710 に答える