我有一个大型Windows窗体应用程序,其中包含最终用户可以使用的大量报表/工作流程。 我正在使用StructureMap for IoC / DI,.Net 3.5
每个报告/路线的元数据由数据库中的行表示。标准的东西,如唯一的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
所需的代码时,处理程序集合为空。
据我在调试器中可以看出,当使用2种方法中的任何一种创建{{1}时,我在ICommand
上传递了一个相同类型的CommandInvoker
传递给Invoke方法}}
我需要更改哪些内容才能使用PrintChecksCommand
?
答案 0 :(得分:1)
解决这个问题的技巧是将Generics添加到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