0

我有一个使用 MEF 实现插件框架的 ASP.NET MVC 应用程序。插件是存在于应用程序 bin 目录中的独立 DLL。插件通常会像这样导出一个或多个控制器...

<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属性中包含所有控制器,并以通常的方式在创建时自行组合。Som_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

所以我的主要问题可以分为两部分:

  1. 如果有 20 个左右的类在实例化时执行组合,是否存在任何明显的性能问题?我目前只有几个,如果有一个命中它并不明显。换句话说,我真的需要改变这个策略吗?它违反了 DRY,因为我Compose在每个班级都有一个方法,但我可以学会接受它。

  2. 有没有更好的办法?如何处理主应用程序中的单个组合,该组合负责填充插件中的所有类,包括那些未在执行主组合的类中导入的类?

我考虑了以下几点:

  • 拥有所有模型和实用程序类以及任何实现标记接口的东西,使用该接口作为协定将它们全部导出,并将它们导入到宿主类中,即使宿主类不需要它们。我认为这是一个比我所拥有的更粗糙的设计,我不想这样做。不过,我愿意听取支持这一点的论点。

  • 在每个需要它的插件中都有一个类,该类实现IWebHost充当主应用程序导出的类的包装器。我仍然需要在每个插件中进行组合,但至少每个插件只需要一次。这个我觉得还可以。

提前感谢您提供的任何帮助,并感谢您阅读整个问题的小说。

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 回答