0

MEF を使用してプラグイン フレームワークを実装する ASP.NET MVC アプリケーションがあります。プラグインは、アプリケーションの bin ディレクトリに存在する別個の DLL です。プラグインは通常、このような 1 つ以上のコントローラーをエクスポートします...

<Export(GetType(IController))>
<MYAPP_Interfaces.Attributes.MVCPluginMetadata(
    "SomePlugin",
    "A Description for the plugin",
    "A Readable Name",
    {"ScriptsForThePlugin.js"},
    {"StylesForThePlugin.css"},
    Enumerations.MVCPluginType.DataView,
    "DefaultActionName")>
<PartCreationPolicy(CreationPolicy.NonShared)>
Public Class MyPluginController
     Inherits System.Web.Mvc.Controller

    <Import()>
    Private m_objHost As IWebHost

... 等々。

これはすべて正常に機能し、ホスト アプリはすべてのコントローラーをImportManyプロパティに含め、通常の方法で作成時に自身を構成します。そのm_objHostため、自動的に入力され、コントローラーはホスト アプリケーションが提供するすべてのもの (ユーザーに関するログや情報、ユーザーが現在取り組んでいることなど) にアクセスできます。

私の質問は、私のモデルと、プラグインにある DAL またはユーティリティ クラスに関するものです。これらのクラスは通常、オブジェクトからの情報を必要としIWebHostます。ただし、ホストはこれらのクラスについて知る必要がないため、構成には含まれません。それらは構成されていないため、IWebHost参照が必要な場合は、次のようにインスタンス化時にそれぞれ構成する必要があります。

Public Class MyModel

<Import()>
Private m_objHost As IWebHost

<Import()>
Private m_objLog As ILog


Public Sub New()
    Compose()
End Sub

...

Private Sub Compose()
    Try
        Dim objCatalog As New AggregateCatalog
        objCatalog.Catalogs.Add(New DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory & "bin"))
        Dim container As New CompositionContainer(objCatalog)
        container.ComposeParts(Me)
    Catch ex As Exception
        If m_objLog IsNot Nothing Then
            m_objLog.writeError(ex)
        End If
    End Try
End Sub
End Class

したがって、私の主な質問は2つの部分に分けることができます:

  1. インスタンス化されるたびにコンポジションを実行する、たとえば 20 程度のクラスを持つことで、顕著なパフォーマンス上の問題はありますか? 現在数枚しか持っていませんが、ヒットしても目立ちません。つまり、実際にこの戦略を変更する必要があるのでしょうか? すべてのクラスにメソッドがあるため、DRY に違反Composeしていますが、それと一緒に暮らすことを学ぶことができます。

  2. より良い方法はありますか?メイン コンポジションを実行するクラスにインポートされていないものを含め、プラグイン内のすべてのクラスを設定するメイン アプリケーションで単一のコンポジションを処理するにはどうすればよいですか?

私は次のことを検討しました:

  • すべてのモデルとユーティリティ クラス、およびマーカー インターフェイスを実装するすべてのものを用意し、そのインターフェイスをコントラクトとして使用してそれらをすべてエクスポートし、ホスト クラスがそれらを必要としない場合でも、それらをホスト クラスにインポートします。これは私が持っているものよりもさらに汚いデザインだと思います。私はそれをしたくありません. しかし、私はこれを支持する議論に喜んで耳を傾けます。

  • IWebHostメインアプリによってエクスポートされたクラスのラッパーとして機能する、それを必要とする各プラグインにクラスを実装します。各プラグインで構成を行う必要がありますが、少なくともプラグインごとに 1 回だけです。これは私には問題ないようです。

あなたが与えることができる助けと、この質問の小説全体を読んでくれてありがとう。

4

1 に答える 1

1

以下のようなクラスを必要なプラグインに追加しました。プラグイン用のプロジェクト テンプレートがあるので、おそらくこのクラスをそのテンプレートに追加します。

ホストから何かを必要とするクラスは、 を呼び出すことでアクセスできますPluginUtility.Host

Public Class PluginUtility

    <Import()>
    Private m_objHost As IWebHost

    Private Shared m_objInstance As PluginUtility

    Private Sub New()
       Compose()
    End Sub

    Public Shared ReadOnly Property Host As IWebHost
        Get
            If m_objInstance Is Nothing Then
                m_objInstance = New PluginUtility
            End If
            Return m_objInstance.m_objHost
        End Get
    End Property

    Private Sub Compose()
        Try
            Dim objCatalog As New AggregateCatalog
            objCatalog.Catalogs.Add(New DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory & "bin"))
            Dim container As New CompositionContainer(objCatalog)
        container.ComposeParts(Me)
        Catch ex As Exception
            Console.Write("Could not compose to get a reference to the host")
        End Try
    End Sub
End Class
于 2013-08-07T21:28:08.903 に答える