0

モデルと実装を可能な限り緩く結合しようとしている状況がありますが、結合が必要以上に近づく可能性があるという状況に直面しています。

私は「モデル」クラスの選択を持っており、すべてがインターフェースを実装しています。さらに、「データアクセス」クラスがあります。このクラスは、整数のルックアップ値を完全な「オブジェクト」表現にデコードする関数を提供します。

モデルクラス内で、モデルがデータアクセスクラスについて知る必要なしに、これらのデコードされた値へのアクセスを提供したいと思います。

簡単な例は次のとおりです。

/// Core classes --

class Car : ICar
{
    public int MakeId { get {...} set { ... } }

    public IMakeInfo Make { get {...} }

    public string Registration { get { ... } set { ... } }

    public int CurrentOwnerId { get { ... } set { ... } }

    public IPerson CurrentOwner { get { ... } }
}

class MakeInfo : IMakeInfo
{
    public string Name { ... }
    public int Id { ... }
    public decimal Weight { ... }
    // etc etc
}

/// Data Access Classes --

class ResolveMake 
{
    public IMakeInfo GetMakeInfo(int id)
    { 
        // Implementation here...
    }

}

クラスがResolveMakeクラスを直接認識せずに、消費するクラスにオブジェクトをCar提供できるようにするにはどうすればよいですか?IMakeInfo実際のインスタンスでは、Carクラスを操作していますが、ResolveMakeクラスと同じ名前空間になく、そのインスタンスへの参照は含まれていません。

私のオプションのいくつか:

  • メソッドCarのインスタンスを提供できるデリゲートを実装します。GetMakeInfo
  • ある種の依存性注入
  • CarをResolveMakeに緊密に結合し、それで完了します。
  • 他のオプションはありますか?

どんな提案も歓迎します!

4

5 に答える 5

1

拡張メソッド

namespace CarStuff
{
   class Car : ICar
   {
      public int MakeId { get {...} set { ... } }
      // no Make property...
      public string Registration { get { ... } set { ... } }
      public int CurrentOwnerId { get { ... } set { ... } }
      public IPerson CurrentOwner { get { ... } }
   }
}


namespace MakeExts
{
   class ResolveMake
   {
      public static IMakeInfo Make(this Car myCar)
      {
         //implementation here
      }
   }
}

他の場所:

using MakeExts;

Car c = new Car();
Console.WriteLine(c.Make().ToString());

編集:.NET 2.0で拡張メソッドを使用するには、次のようなものが必要です。

基本的に、以下を含むクラス:

namespace System.Runtime.CompilerServices 
{ 
   class ExtensionAttribute : Attribute
   {
   }
 }

そして、関連する場所に散在する「usingSystem.Runtime.CompilerServices」。

于 2009-06-22T08:32:44.337 に答える
1

私には依存性注入のように聞こえます。私はMSPPUnityで同様のことを行い、コンストラクターインジェクションとメソッドおよびプロパティインジェクションの両方を実行しました。次に、CarクラスにIMakeInfoのある種のインジェクションがあります...例:

[InjectionMethod]
public void Initialize([Dependency] IMakeInfo makeInfo)
{
  this.MakeInfo = makeInfo;
}
于 2009-06-22T08:33:52.867 に答える
0

CarクラスにはIMakeInfoを返すプロパティMakeがあるため、すでに情報を提供しているように見えます。それで、あなたの問題は、車に返品する価値をどのように提供するかということであると私は思いますか?

この場合、車とResolveMakeについて知っているファクトリメソッドの作成を検討することをお勧めします。

于 2009-06-22T08:32:52.917 に答える
0

例えれば、車はget_MakeがIMakeInfoと呼ばれるまでに明らかに知る必要があります。私はまた、車の重要な特徴を作ることを考えます。したがって、IMakeInfoをCarコンストラクターに渡す(おそらくIOCを使用する)のは非常に合理的だと思います。これが実際のコードによく似ている場合(各「車」には単一の固有の「IMakeInfo」があります)、これを使用します。

Johanが言ったように、オプションのIOCを使用してセッターを使用することもできます。私がコンストラクターを好む理由は、すべての「車」に「メイク」が必要なように見えるからです。

于 2009-06-22T08:39:04.980 に答える
0

結局(私が取り組んでいた制約を考えると)、私は実際に上記のいくつかのテーマのバリエーションを使用しました。

循環参照が発生するためにデータアクセス層への参照を回避する必要があったため、デリゲートと「ファクトリ」コードを使用して何かを行うことになりました。それを私の元のシナリオに合わせて、私は次のことをしました:

class Car 
{
    public void SetLookupProvider(ILookupProvider value) { _lookupProvider = value; }

    public IMakeInfo Make { get { return _lookupProvider.ResolveMake(MakeId); } }

    ....
}

interface ILookupProvider
{
    IMakeInfo ResolveMake(int id);
}

class LookupProvider
{
    public delegate IMakeInfo ResolveMakeDelegate(int id);

    public ResolveMakeDelegate ResolveMakeDel { set { _resolvemake = value; } }

    public IMakeInfo ResolveMake(int id){ return _resolvemake(id); }  
}

それから私のファクトリメソッドでは...

ICar returnedObject = new Car(blah, foo, bar, etc);

ILookupProvider luprovider = new LookupProvider();
luprovider.ResolveMakeDel = DataAccessLayer.FunctToGetMakeInfo;

(Car)returnedObject.SetLookupProvider(luprovider).

今、私はこれが最も美しい解決策ではないことを認める最初の人です(3.0コンパイラにアクセスした場合はExtensionメソッドを使用していました)が、CarクラスはDataAccessレイヤー(私の状況は循環参照地獄を防ぎました...)。Carクラスは、結果がどのように取得されるかを知る必要はありません。最初にCarオブジェクトを生成するファクトリメソッドは、データアクセス層に結合される唯一のものです。

私はまだ答えをマークしていません。さらに数人に投票させてから、最高の投票を行います。特に、それらはすべて有効な答えだと思います(この場合、1つも完全に使用できなかっただけです)。 。

于 2009-06-23T12:41:44.170 に答える