2

私は、階層的に編成された一連のクラスを持つサードパーティのアセンブリを使用しています。CreateXxx()これらにはプライベート コンストラクターがあり、1 レベル上の別のクラスのインスタンスでメソッドを呼び出すことによってインスタンス化されます。階層の最上位では、シングルトン クラスが使用されます。たとえば、アプリケーション コードは次のようになります。

TopClass top = TopClass.GetInstance();
SecondLevelClass secondLevel = top.CreateSecondLevelElement();
ThirdLevelClass thirdLevel = secondLevel.CreateThirdLevelElement();

同様に、ファイナライズはDeleteXxx()メソッドを使用して行われます。これは、 に使用される同じオブジェクトで発生する必要がありますCreateXxx()

この特定のアプローチが採用された理由については説明しません。ただし、これらのクラスの作成を、パブリック コンストラクターを持つ独自のクラス セットでカプセル化して、次のようにコードの見栄えを良くしたいと考えています。

// No TopClass anymore, see explanation below
MySecondLevelClass secondLevel = new MySecondLevelClass();
MyThirdLevelClass thirdLevel = new MyThirdLevelClass(secondLevel);

私の最初のアプローチは、MyXxxクラスがCreateXxx()コンストラクターで関連するメソッドを呼び出し、結果への参照を維持することでした。DeleteXxx()また、ファイナライズ時にメソッドを呼び出すには、コンストラクター パラメーターへの参照が必要です。そのためには、内部で実装IDisposableして呼び出すことを考えていました。DeleteXxx()Dispose()

このアプローチではTopClass、SecondLevelClass インスタンスの作成と破棄が唯一の目的であるため、アプリケーション開発者にとって は不要になりました。これは、MySecondLevelClassコンストラクター内のボンネットの下で発生するようになりました。

全体として、これは技術的に健全だと思います。MyXxx私が遭遇する唯一の問題は、元のクラスが多くのメソッドを持つインターフェイスを実装しているという事実です。これは、まだクラスを介して公開したいと考えています。私は自分のクラスでこれらすべてのメソッドを再定義することを楽しみにしていません。すべての呼び出しを「元の」クラスのインスタンスへのカプセル化された参照に転送するだけです。ドット演算子をオーバーロードするようなことができればいいのですが。または、元のクラスのインスタンスへのカプセル化された参照が実際にインターフェイスを実装していることをコンパイラに伝えるとよいでしょう。つまり、VMT に特別な間接化を追加するようなものです。

もちろん、これらのオプションはサポートされておらず、すべてのメソッドのこの重複を回避する方法は見つかりませんでした。よりスマートな方法でこれを行う方法を知っている人はいますか? 事前に感謝します。

4

2 に答える 2

1

おそらく、既存のクラスをラップするのではなく、ビルダーパターンのようなものを使用してそれらの構造をラップすることができます。'TopClass o = new TopClass()'構文は取得できませんが、このような構築パターンは十分に理解されており、コードの理解を深める必要があります。

(基本的な)ビルダーは次のようになります。

public class OtherAssemblyBuilder
{
    public TopClass Build()
    {
        return TopClass.GetInstance();
    }

    public SecondLevelClass Build()
    {
        TopClass top = TopClass.GetInstance();
        return top.CreateSecondLevelElement();
    }

    public ThirdLevelClass Build()
    {
        TopClass top = TopClass.GetInstance();
        SecondLevelClass secondLevel = top.CreateSecondLevelElement();
        return secondLevel.CreateThirdLevelElement();
    }
}
于 2012-06-27T02:52:03.673 に答える
0

これを達成できる唯一の方法は(私の知る限り)、次のようなことをすることです-


public class Concrete : SomeInterface
{
    private Concrete()
    {
        //instantiate other classes here
    }
    public string GetAString()
    {
        return string.Empty;
    }

    public static Concrete GetInstance()
    {
        return new Concrete();
    }

}

public class Wrapper : SomeInterface
{
    public Wrapper()
    {
        this.concrete = Concrete.GetInstance();
    }
    Concrete concrete { get; set; }
    public string GetAString()
    {
        this.concrete.GetAString();
    }
}

public interface SomeInterface
{
    string GetAString();
}

ラップしているクラスの各インターフェイス メンバーを手動で呼び出す必要があるため、これが最善のアプローチではないことはわかっていますが、目標は達成されます。

T4 コード テンプレートを試してみませんか?この状況に頻繁に遭遇する場合 (およびインターフェイスが変更される場合)、将来的に時間を節約できる可能性がありますか?

于 2012-06-27T02:18:22.740 に答える