web-dev-qa-db-ja.com

COMの制限を考慮して.NETライブラリを作成するか、.NETライブラリをInteropから分離する方が良いですか?

私はこの興味深い記事に出くわしました: COMの相互運用性が好きになりました CodeProjectで、私は考えさせられました...

著者は、.NETライブラリの美しさを損なうため、.NETライブラリにCOM-ityを必要としないと主張しています。代わりに、.NETライブラリをCOMに公開する個別の相互運用ライブラリを作成します。この相互運用ライブラリは、COMがパラメーター、オーバーロードされたメソッド、ジェネリックス、継承、静的メソッドなどのコンストラクターをサポートしないという事実を処理します。

そして、それは非常に斬新なことだと思いますが、それだけでプロジェクトを完成させるのではないでしょうか。

  • 次に、.NETライブラリとInteropライブラリを単体テストする必要があります。
  • 次に、美しい.NETライブラリを回避してCOMに公開する方法を理解するために時間を費やす必要があります。
  • クラス数を効果的に2倍または3倍にする必要があります。

COMと非COMの両方をサポートするためにライブラリが必要かどうかは確かに理解できます。ただし、COMのみを使用する場合、この種の設計は私には見られない利点をもたらしますか? C#言語の利点しか得られませんか?

または、ラッパーを提供することでライブラリのバージョン管理を容易にしますか? COMを使用する必要がないため、単体テストの実行が速くなりますか?

9
robodude666

ただし、COMのみを使用する場合、この種の設計は私には見られない利点をもたらしますか?

あなたの質問のこの抜粋は、ここでの設計決定のthe最も重要な部分であり、答えは(いつものように)それは依存します

COM Interop経由でのみライブラリを使用する場合は、これを考慮してシステム全体を設計する必要があります。行数を3倍にする理由はありません。システムのLoCが多ければ多いほど、システムの欠陥も多くなります。したがって、COM互換機能のみを使用するようにシステムを設計する必要があります。

ただし、. Netライブラリの使用を制限する正当な理由は考えられませんCOMに。 他の.Netコードでアセンブリを使用できないようにする理由はなぜですか?この方法で自分を制限することはほとんど意味がありません。

これについてはある程度の経験があるので、それをどのように処理したかを共有します。その確かに理想的ではありません。私はいくつかのトレードオフをしました。私は、新しい.Netイディオムと互換性のないCOMクラス(実際にはインターフェイス)のファサードのみを使用しています。それ以外の場合は、.NetインターフェイスをCOMに直接公開します。これは基本的に、ジェネリックを使用するすべてのインターフェースにファサードを使用することを意味します。ジェネリックスは私が遭遇した唯一の互換性のないものです。残念ながら、これはIEnumerable<T>を返すすべてのファサードを意味しますが、これはかなり一般的です。

ただし、ファサードクラスは.Netクラスを継承し、特定のInteropインターフェイスを実装しているため、見た目ほど悪くはありません。このようなもの。

namespace Company.Product.Feature
{
    public class MyClass : INetInterface 
    {
        // lots of code
    }
}

namespace Company.Product.Interop
{
    public class MyClass : Feature.MyClass, IComInterface
    {
        // over ride only the  incompatible properties/methods
    }
}

これにより、重複するコードが最小限に抑えられ、「意図しない」変更からCOMインターフェイスが保護されます。コアクラス/インターフェイスが変更されると、アダプタークラスはより多くのメソッドを乗り越える必要があります(またはインターフェイスを壊してメジャーバージョン番号を上げる必要があります)。一方、InteropコードのすべてがInterop名前空間に保存されるわけではないため、ファイルの整理が混乱する可能性があります。私が言ったように、それはトレードオフです。

この完全な例については、私のリポジトリの SourceControl および Interop フォルダを参照できます。 ISourceControlProviderGitProviderは特に重要です。

7
RubberDuck

.NETライブラリの美しさを取り除きます

その作者は、目を覚ますスラップが必要です。あらゆるプロフェッショナルプロジェクトの目標は、人々が使用したい実用的なソフトウェアを作成することです。美についてのあらゆる種類の誤った理想はその後ずっとやって来る。それが彼らの唯一の理由である場合、著者はすべての信頼性を失っています。

クラスをcom-visibleとしてマークでき、COMを介して.NETコードと通信できることは、非常に便利です。美しさのための生産性へのその大きな利益を捨てることは狂気です。

ただし、COMで物事を機能させるにはいくつかのトレードオフが必要です。引数のないコンストラクターが必要なのはその1つであり、その他のいくつかはあなたが言及したものです。いずれにせよ、これらの機能を使用していない場合、または機能を使用しなくても問題がない場合は、COMと非COMに同じクラスを使用することで、多くの作業を節約できます。

一方、COMクライアントが劇的に異なるインターフェイスを期待している場合、依存関係または.NETクラスで扱いにくい他の制限がある場合、または.NETクラスを大幅に変更する予定で、COMを後方に維持する必要がある場合互換性を確保するために、Interopクラスを作成して、そのギャップを埋めてください。

しかし、「美」については考えないでください。 .NETを介してCOMを公開できることは、作業を節約するためのものです。自分のためにもっと仕事を作成しないでください。

7
whatsisname

まあ、公平に言うと、その記事の元の作者は彼の記事のどこにも「美」という言葉を使用していませんでした。自分自身。

私がその記事を理解している限り、.NETライブラリはすでに存在し、COMを考慮せずに作成されました。おそらく、ライブラリが作成された時点では、COMをサポートする必要がないためです。

その後、COMをサポートするという追加の要件が導入されました。このような状況に直面した場合、2つのオプションがあります。

  • 元のlibを再設計して、COM相互運用機能と互換性があるようにします(物を壊すリスクがあります)。

  • 元の作業ライブラリをほとんどそのままにして、代わりに「ラッパー」(または「アダプタ」)の機能を使用して別のアセンブリを作成します

ラッパーまたはアダプターの作成は よく知られている設計パターン (またはこの場合はより多くの建築パターン)であり、長所と短所もよく知られています。それに対する一つの議論はより良い「懸念の分離」であり、それは美しさとは何の関係もありません。

あなたの懸念に

次に、.NETライブラリとInteropライブラリを単体テストする必要があります。

再設計によってCOMインターフェイスを既存の.NETライブラリに導入する場合は、そのインターフェイスもテストする必要があります。手動で作成されたアダプターを導入するには、インターフェースが機能しているという追加のテストが必要になる場合がありますが、libのコアビジネス機能のすべての単体テストをコピーする必要はありません。 libへの単なるインターフェースの1つであることを忘れないでください。

次に、美しい.NETライブラリを回避してCOMに公開する方法を理解するために時間を費やす必要があります。

元のライブラリを再設計する必要がある場合は、それも理解する必要があり、さらに多くの作業が必要になると思います。

クラス数を効果的に2倍または3倍にする必要があります。

元のライブラリの一部のクラスの一部である、パブリックCOMインターフェイスを介して公開されるクラスのみ。

あなたが言及した別の状況では、最初から一流の市民としてCOMをサポートする必要があることがすでにわかっている場合、私はあなたが正しいと思います:個別のアダプターlibを追加する手間を省き、 COMを直接サポートする.NET lib。

3
Doc Brown