0

我有一个大型 Windows 窗体应用程序,其中包含最终用户可以使用的大量报告/工作流。我正在为 IoC/DI、.Net 3.5 使用 StructureMap

这些报告/路线中的每一个的元数据由数据库中的行表示。标准的东西,比如唯一的 rowID、报告名称、几个描述性的句子。

目前我有一个班级负责启动每个报告。这是一个庞大的 Case 语句,如下所示:

Public Sub LaunchSomething(launchRequest as LaunchItemInfo)
  Dim cmd as ICommand
  Select Case launchRequest.UniqueId
  Case 1
    cmd = New Reports.AccountsPayable.PrintChecksCommand
  Case 2
    cmd = New SomeOtherCommandClass
  ..
  Case 400
    cmd = New Report400Class
  End Select

    AppController.Commands.Invoke(cmd)
  End Sub

我真的希望能够使用这样的代码:

Public Sub LaunchSomething(launchRequest as LaunchItemInfo)
  Dim cmd as ICommand
  Dim typ as Type
  typ = Type.GetType(launchRequest.ReportClassName, launchRequest.FileContainingReportClass)
  cmd = Activator.CreateInstance(typ)
  AppController.Commands.Invoke(cmd)
End Sub

这些是我正在使用的支持接口和类。ICommand 只是一个标记接口

Public Interface ICommand
End Interface

Public Interface ICommandHandler(Of C As ICommand)
    Sub Handle(cmd As C)
End Interface

Public Class PrintChecksCommand
    Implements ICommand
End Class

AppController.Commands 是一个 CommandInvoker,Invoke 方法如下所示:

Public Sub Invoke(Of C As ICommand)(ByVal command As C)
  Dim handlers as Generic.IList(Of IcommandHandler(Of C))
  handlers = ObjectFactory.GetAllInstances(Of ICommandHandler(Of C))()
  For each h as ICommandHandler(Of C) in handlers
    h.Handle(command)
 Next
 End Sub

当我将原始代码与 400 多个 Case 语句一起使用时,处理程序集合正确地包含 1 个项目。所以我知道我的结构映射注册表设置正确。

当我尝试使用所需的代码时Activator.CreateInstance,处理程序集合为空。

据我在调试器中可以看出,当使用这两种方法中的任何一种来ICommand创建CommandInvokerPrintChecksCommand

我需要更改什么才能在Activator.CreateInstance(typ)此处使用?

4

1 回答 1

1

解决这个问题的诀窍是将泛型添加到 ICommand 接口,并利用 CommandInvoker 中的额外信息。

接口/类现在看起来像这样:

Public Interface ICommand(Of T)  
End Interface  

Public Interface ICommandHandler(Of T as ICommand(Of T))
  Sub Handle(cmd as T)  
End Interface

Public Interface ICommandInvoker  
    Sub Invoke(Of T As ICommand(Of T))(ByVal command As ICommand(Of T))  
End Interface  

Public Class CommandInvoker  
      Implements ICommandInvoker  
    Public Sub Invoke(Of T As ICommand(Of T))(command As ICommand(Of T)) Implements ICommandInvoker.Invoke
    Dim handlers As Generic.IList(Of ICommandHandler(Of T)) = Nothing  
    handlers = ioc.GetAllInstances(Of ICommandHandler(Of T))()  
    For Each h As ICommandHandler(Of T) In handlers  
        h.Handle(command)  
    Next  
    End Sub  
End Class

Public Class DoSomethingCommand
    Implements ICommand(Of DoSomethingCommand)
    Public Sub New()
    End Sub
End Class

Public Class SomethingHandler
    Implements ICommandHandler(Of DoSomethingCommand)

    Public Sub New()
    End Sub

    Public Sub Handle(cmd As DoSomethingCommand) Implements ICommandHandler(Of DoSomethingCommand).Handle
    End Sub
End Class
于 2013-09-13T18:40:05.287 回答