2

重複の可能性:
StructureMap シングルトンの使用 (2 つのインターフェイスを実装するクラス)

私は現在小さなシステムを設計しており、現在構造マップを IoC として使用しています。私は最近、インターフェイスの分離のポイントを得ました...そして今疑問に思っています。

たとえば、3 つのインターフェイスを実装する特定のビジネス オブジェクトがある場合、コードの構成と挿入でこれをどのように処理すればよいでしょうか。

単純なシナリオで、EmployeeServiceObject というサービス層クラス用に 2 つのインターフェイスがあると仮定します。IGenericEntity および IEmployeeServiceObject。

GenericEntity はクラスの CRUD 機能を提供し、IEmployeeServiceObject はビジネス クエリ/操作の結果セットを提供します。

Facade/Service Layer メソッドで、EmployeeServiceObject クラスを使用し、実際に両方のインターフェイスの機能を使用する必要がある場合...これをどのように処理する必要がありますか?

最初は、IoC の構成をセットアップして IEmployeeServiceObject を EmployeeServiceObject にマップし、ファクトリにオブジェクトを要求し、CRUD 機能を使用する必要があるときにそれを IGenericEntity にキャストするのが正しいと思っていましたが、よくわかりません。 . 具象クラスが ioc コンテナー構成でセットアップされていないインターフェースを実際に実装していると正式に述べることは決してないため、それも正しくないようです。

そして、同じ具象クラスの 2 つのインスタンスを作成するが、別のインターフェイスを要求することは確かにわかっています...さらに悪いことに聞こえます。

これはどのように処理する必要がありますか?

4

3 に答える 3

2

質問を正しく理解している場合は、次のシナリオがあります(C#コード)。

public interface IGenericEntity { /**/ }

public interface IEmployeeServiceObject { /**/ }

public class EmployeeServiceObject : IEmployeeServiceObject, IGenericEntity

その場合、EmployeeServiceObjectが両方のインターフェースを実装するという事実は、実装の詳細です。各インターフェースを個別に実装する他の実装がある場合があります。

ISPのポイントは、各インターフェイスが個別の関心事をモデル化することです。したがって、IGenericEntityとIEmployeeServiceObjectの両方が必要な状況に頻繁に遭遇する場合は、2つのインターフェイスへの分離が意味があるかどうかを疑問視する必要があります

それ以外の場合は、キャストしようとするとリスコフの置換原則に違反するため、各インターフェイスを個別にリクエストする必要があります。

本当に両方が必要な場合は、両方をリクエストする必要があります。

public class Foo
{
    public Foo(IGenericEntity ge, IEmployeeServiceObject eso) { /**/ }

    // ...
}

1つのクラス(EployeeServiceObject)が両方のインターフェースを実装している場合は、これが当てはまることをDIコンテナーに通知する必要があります。この時点で、コンテナ固有の詳細の領域に移動しているため、その方法はコンテナごとに異なります。

たとえば、Windsorには、あるインターフェイスのリクエストを別のタイプに転送するように指定できるForwardメソッドがあります。

貧乏人のDIではそれは同じくらい簡単です

var eso = new EmployeeServiceObject();
var f = new Foo(eso, eso);

Poor ManのDIを使用して依存関係階層を構成する方法を理解することは常に良いことです。これは、コンテナーが同じことをどのように理解するかについての貴重な手がかりを与えることができるためです。

于 2010-04-08T07:04:55.707 に答える
0

質問を重複として閉じる方法が見つかりませんでした...しかし、別のスタックオーバーフローの質問で必要なことを正確に行う方法を見つけました。

MarkがWindsorのForwardメソッドとして言及したことは、StructureMapにも存在します...そしてそれは物事を行う正しい方法であるように思われます。

StructureMapシングルトンの使用法(2つのインターフェイスを実装するクラス)

于 2010-04-08T17:12:34.400 に答える
0

よろしければ、DI/IoC の実装に対処する前に、API に対処したいと思います。あなたの問題点は、あなたをより良いデザインに導こうとしていると思います。

EmployeeServiceObject の責任が多すぎるようです。オブジェクトを作成するときは、単一​​責任の原則を考慮してください。あなたの説明では、EmployeeServiceObject はファサード/サービス レイヤーCRUD レイヤーの両方です。CRUD 操作 (IGenericEntity) のインターフェイスを割り当てることにより、CRUD 実装をファサード (IEmployeeServiceObject) のコンシューマーに公開します。

この状況とあなたが説明したタイプを考慮して、別のアプローチを検討してください(タイプ名を再検討して、その目的をより正確に説明します):

public interface IEmployeeServiceObject 
{
    // Service methods
    decimal GetSalary(string employeeId);
}

public class EmployeeServiceObject : IEmployeeServiceObject
{
    private IGenericEntity<Employee> _entity;

    public EmployeeServiceObject(IGenericEntity<Employee> entity)
    {
        _entity=entity;
    }

    public decimal GetSalary(string employeeId)
    {
        return _entity.Get(employeeId).Salary;
    }
}

public interface IGenericEntity<T>
{
    // CRUD Methods including...
    T Get(string id);
}

public class GenericEntity<T> : IGenericEntity<T> 
{
    T Get(string id){...}
}

IEmployeeServiceObject/EmployeeServiceObject と IGenericEntity/GenericEntity のペアを選択したコンテナーに登録します。(StructureMap は、慣例によりこれらの型を登録できます。)

コンテナーから IEmployeeServiceObject を要求すると、コンテナーは GenericEntity を提供する前に EmployeeServiceObject のコンストラクターに挿入します。

このようにして、説明したキャスト/登録の問題を回避します。コンテナが最適ではない方法で動作するように強制する必要はありません。さらに、ファサードはクライアントが必要とするものだけを公開し、CRUD 操作を別のクラス (クライアントに公開する必要がない) に任せます。

于 2010-04-08T07:14:28.737 に答える