我打算问一个相当复杂的问题,这也是的东西在这里沉思,如此忍受我...复杂的.NET工厂设计
我试图设计一个工厂实现了模拟应用。该模拟将由不同种类的实体组成,即它在任何方面都不是均质模拟。因此,将会有许多非常不同的具体实现,只有非常普遍的属性才会在顶层抽象出来。
我想要做的就是通过调用模型上的一个方法来创建新的模拟实体,其中包含一系列代表实体参数的命名参数,并让模型推断出什么类型的对象由入站参数(从参数的名称以及它们出现的顺序)描述,并在适当的派生类上调用工厂方法。例如,如果我传递模型一对参数(Param1 = 5000,Param2 =“Bacon”),我希望它推断名称Param1和Param2'属于'Blob1类并且调用一个名为参数Param1:= 5000,Param2:=“Bacon”的共享函数“getBlob1”,而如果我传递模型(Param1 = 5000,Param3 = 50),它会为Blob2调用一个类似的工厂方法;因为Param1和Param3按顺序'属于'Blob2。
我预见几个问题需要解决:
- 不论是否我能在可用类型的字符串参数的名称,以及如何做到这一点反映,如果有可能
- 无论是否有一个整洁的方式从参数列表的组合属性中进行适当的构造函数推理,或者我将不得不躲过某些“手工”操作。
- 如果可能,我希望模型类能够接受参数作为参数而不是一些键和值的集合,这将需要模型在运行时暴露大量参数化方法,而不需要我可以明确地对它们进行编码 - 大概是针对相关名称空间中可用的每种工厂方法的编码。
我真正要问的是如何执行这样的系统,而不是从根本上是否可行。我没有.NET反思的先见之明或经验能够自己找出方法。希望这将证明一个信息丰富的讨论。
UPDATE:
好了,我已经在实现一个简单的例子,一个玩具模型,本质上是一个裂缝。核心逻辑如下:
Dim members() As Reflection.MethodInfo = Me.GetType.GetMethods()
Dim params_enum As IEnumerator(Of String) = params.Keys.GetEnumerator
While params_enum.MoveNext
members = Array.FindAll(members, _
Function(m As Reflection.MethodInfo) Array.Exists(CType(m, Reflection.MethodInfo).GetParameters(), _
Function(mm As Reflection.ParameterInfo) mm.Name = params_enum.Current))
If members.Count = 0 Then Return False
End While
Try
CType(members(0), Reflection.MethodInfo).Invoke(Me, params.Values.ToArray())
Return True
Catch ex As Exception
Return False
End Try
这只是在当前实例上选择一个方法并执行它。我想把它扩展到程序集中所有类型的子集。如果可能的话,我也想这样做,通过检查它们自己的属性,让这些类型决定它们在运行时的参数初始化要求是什么,即每个标有'ParametrisedInitAttribute'的属性都对应于工厂方法中的一个命名参数。这将要求我有这些类型在运行时公开一个N参数的方法。有没有办法构造一个具有任意签名的方法,并在运行时将其添加到类实现中,或者采用类似的方法来执行此类事情?
是否修复了可能参数名称的总集合?并且每个特定的参数是否有固定的类型? – tzaman 2010-06-12 11:13:23
tzaman:好问题。我想答案是'这取决于';因为我还没有决定。我想到的是能够允许用户使用(例如)Excel数据的简单拖放/复制粘贴来配置模型;并且该模型通过存在的值的组合来推断用户想要添加的对象。理想情况下,模型可以猜测每个字段在标题被省略或什么时候意味着什么。一般来说,整套参数在运行时会被模型知道,而不是设计时间,但之后会被修复。 – 2010-06-12 11:20:25
顺便说一句,我希望这个功能的另一个原因是程序架构的原因 - 关注点和分层功能的分离,我希望UI展示者能够简单地在模型中引入一堆值,并假设如果需要的话,它知道如何处理它们。 – 2010-06-12 11:25:30