编写未由执行合成的类导入的零件的好方法是什么?

时间:2013-07-26 14:35:11

标签: asp.net-mvc mef composition

我有一个ASP.NET MVC应用程序,它使用MEF来实现插件框架。插件是存在于应用程序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属性中的所有控制器,并以通常的方式创建时自行组合。因此,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

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

  1. 是否有任何明显的性能问题,例如,20个左右的类在实例化时执行组合?我目前只有一些,如果有一个打击它不明显。 换句话说,我是否真的需要更改此策略?它违反了DRY,因为我在每个课程中都有Compose方法,但我可以学会使用它。

  2. 有更好的方法吗?如何在主应用程序中处理单个组合,负责填充插件中的所有类,包括那些未在类中导入的类表演主要作品?

  3. 我考虑过以下几点:

    • 拥有所有模型和实用程序类以及实现标记接口的任何内容,使用该接口将它们全部导出为合同,并将它们导入到宿主类中,即使宿主类不需要它们也是如此。我认为这比我的设计更加惹人讨厌,而且我不想这样做。不过,我愿意听取有利于此的论据。

    • 在每个需要它的插件中都有一个类来实现IWebHost,它充当主应用程序导出的类的包装器。我仍然需要在每个插件中进行组合,但至少每个插件只需要一次。这个对我来说似乎没问题。

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

1 个答案:

答案 0 :(得分: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