6

私は非常に大きなクラスAを持っており、多くのメンバーがいます。また、Aオブジェクトを持っているときに構築できる非常に大きなクラスBがあります。Bオブジェクトがある場合、Aオブジェクトを作成できます。Aは検証機能を備えた一種のViewModelであり、Bは簡単にプロットできるグラフィカルな記述であるため、両方が必要です。

この変換を行う方法は?

これが私がやりたいことを説明するための例です:

class A
{
    string s;
    string t;
    string u;
    string v;

    enum a;
    enum b;
    enum c;
    enum d;
    enum e;

    Dictionary<enum, string> dict;
}


class B
{
    string someString; // is essentially A.a + A.b + A.c + A.s with some rules.
    int someValue; // is essentially dict.TryGetValue(enum.Entry);
    string anotherString;
    // ... and lots of others
}

もちろん、いくつかのマッピングを実行してBオブジェクトを構築するのは簡単であり、A=>Bを構築するルールを逆にしてプレーンなB=>Aマッピングを作成することはそれほど難しくありません。

したがって、質問は次のとおりです。

  • それを達成するためのよく知られたパターンはありますか?
  • そのようなことを行うデフォルトのC#の方法はありますか?

そのような単純なものを書き留めると、収まらないように見え、数百行のコードになってしまいます。

SomeStringConverter、SomeValueConverter、...などのパーツのコンバータークラスの種類について考えました。

  • マッピングを行うためのルールとともに、Aの必要なメンバーを抽象化するにはどうすればよいですか。
  • A=>BおよびB=>Aを実行する最も簡単な方法を持つように、これらのルールをどのように記述できますか。

編集: ここでのパターンは、「GoFデザインパターン」ではなく「ベストプラクティス」を意味します。

BクラスのSomeStringはある種の「セレクター」であり、描画オプションを選択します。これは常に25文字の長さで、クラスAの列挙型はそれらの文字を選択しますが、ほとんどの場合1対1ではありません。

たとえば、次のように考えます。Aa = "Filled"、Ab = "SingleCoordinate"、Ac = "DrawHints"は、SomeString=のような結果になります。

 "Y**D***RR****---***---***"

つまり、このような文字列を取得するには組み合わせが重要ですが、組み合わせから、Aオブジェクトに設定する必要のある列挙型を導出できます。

Edit2:

マッピングルールを両方の方法で使用する方法に特に興味があります。つまり、Aa="Filled"とAb="SingleCoordinate"を組み合わせて、Ac = "DrawHints"と組み合わせると、(部分文字列)"Y**D***RR"になり、その部分文字列は次のようになります。そのAaは「Filled」などに設定する必要があります。

4

5 に答える 5

4

A はデータ モデルに、B はビュー モデルに近いように思えます。この種のインスタンスに一般的に受け入れられている「パターン」はないと思います。主な理由は、この種のペアリングの背後にある理由はさまざまであり、最適なパターンは使用目的に大きく依存するためです。

とはいえ、それらは非常に密接に結びついているため、あるクラスを別のクラスに従属させる傾向があります. この場合、A の方が単純なので、おそらく A を B のデータ コンテナーとして使用します。つまり、プライベート メンバー A をクラス B のフィールドとして持ち、クラス B のすべてのプロパティがクラス A を直接参照します。独自のプライベート フィールドを後ろに持つのではなく。次に、必要に応じて、クラス A のプライベート メンバーを公開するクラス B にパブリック プロパティを設定できます。私はおそらくそれを読み取り専用のままにしておくでしょうが、それはおそらくそれほど重要ではありません (クラス B の使用と可能なバインドされた関係によって異なります)。逆に、クラス A をパラメーターとして受け入れるコンストラクターをクラス B に作成します。渡された A の値は、クラス B のプライベート クラス A メンバーに割り当てられます。

すべての結果は、クラス A がクラス B を無視することを維持することです。これは、ViewModel 状況の真のユースケースがある場合に役立ちます。クラス A が必要に応じてより正しい ViewModel であると判断した場合は、上記を逆にして、クラス B がクラス A を認識しないようにします。

于 2012-07-03T21:15:56.343 に答える
3

それを達成するためのよく知られたパターンはありますか?

パターンの意味によって異なります。DecoratorまたはAdapterパターンが思い浮かびますが、どちらも型をさまざまな型に大規模にマッピングするためのものではありません。

そのようなことを行うデフォルトの C# の方法はありますか?

いいえ、ありません。しかし、Automapperのようなライブラリは確実に生活を楽にしてくれます。

于 2012-06-26T19:16:38.710 に答える
0

What I have done to solve this problem:

  1. Wrote a BiMap (with the help of older SOs on that issue).

  2. Inserted the Mapping into it (all value combinations in Key, the resulting key in the "Value", together with a BitArray which specifies the indices of the string that are defined by that mapping.

  3. Wrote some code to calculate a resulting overall string from it, as the mapping will just give partial strings.

  4. The one-to-one mappings were trivial.

That way I could use the mappings in both ways. Given a string, I still have a quite expensive search (as I have to compute the stored string utilizing the BitArray as a mask)

At the moment it seems to work very good, but I'm not finished yet.

Thank you all for your very good ideas and approaches! Perhaps AutoMapper can do this, but I do not have much time at the moment to read and try out a new technology.

If anybody can provide some relevant examples on how to do this on Automapper, I will accept it as an answer (as I already love AutoMapper).

Examples like lets say: 3 enums with 5 values to one fixed length string one fixed length string to 3 enum with 5 values (the reverse of the above).

as an example:

A.a && B.o && C.y ==> "**A**********************"
A.a && B.p && C.y ==> "**B**********************"
A.b && B.o && C.y ==> "*****X*******************"
A.b && B.o && C.z ==> "*****W*******************"

Can Automapper achieve such things?

于 2012-07-03T21:02:47.300 に答える
0

いくつかの考え:

A) B を A が実装するインターフェースに変更します。これにより、B のプロパティを再作成することなく、A のプロパティに直接「マップ」できます。B に、A が持つべきではないプロパティ (または A のいくつかを組み合わせたプロパティ) がある場合、アクセス修飾子を private* に設定できます。つまり、プロパティはインターフェイスを介してのみ表示されます ( A) の実装を混乱させたり混乱させたりします。

B) 擬似アダプター/ラッパー パターンを使用します。B は、型 A のコンストラクター パラメーターを指定すると、A のプロパティなどを参照できます。B が異なる場合は、独自のロジックを実装できます。

2 つの複雑なオブジェクト間のマッピングには、複雑な思考が必要です。特別なケース、副作用、および長所と短所の考慮とバランスを必要とする選択が常に存在します。(たとえば、文字列と整数の間で変換すると、あらゆる種類の質問が発生します。3 桁の区切り記号をどうするか、異なる文化を処理する方法など)。特定の状況を読んでも、簡単で迅速な方法がわかりません。マッピングを処理します-関連するすべての要因に基づいた方法を使用しますが、おそらくここに投稿するには多すぎます.

編集: * これは、私がいくつかの VB プロジェクトで行ったことであることに注意してください。これはC#では合法だと思いますが、試したことはありません。

于 2012-07-02T16:12:55.147 に答える
0

工場 + おそらくファサード

A から B を構築するか、B から A を構築するかを調整したいと考えています。これは、そのために複雑なロジックが必要であることを示しています。

A から B を構築するには、B に静的メソッドとして実装する (Factory) か、B から継承し、A をコンストラクター (Facade) の引数として受け取る新しいクラス C を作成します。

工場: http://en.wikipedia.org/wiki/Factory_method_pattern (状況に完全に一致するわけではありません)

Facade: http://en.wikipedia.org/wiki/Design_Pattern_-_Facade (どちらも完全一致ではありません)

于 2012-06-29T06:42:41.027 に答える