【发布时间】:2011-03-02 23:36:43
【问题描述】:
我打算问一个相当复杂的问题,在这里也是一种沉思,所以请耐心等待......
我正在尝试为模拟应用程序设计工厂实现。模拟将由不同种类的实体组成,即它在任何方面都不是同质模拟。因此,将有许多非常不同的具体实现,只有非常一般的属性会在顶层抽象出来。
我想做的是通过在模型上调用一个方法来创建新的模拟实体,该方法使用一系列代表实体参数的命名参数,并让模型推断正在描述的对象类型通过入站参数(来自参数的名称以及它们可能出现的顺序)并在适当的派生类上调用工厂方法。
例如,如果我向模型传递一对参数 (Param1=5000, Param2="Bacon"),我希望它推断名称 Param1 和 Param2“属于”类“Blob1”并调用具有命名参数 Param1:=5000, Param2:="Bacon" 的共享函数“getBlob1”,而如果我传递模型 (Param1=5000, Param3=50),它将为 Blob2 调用类似的工厂方法;因为 Param1 和 Param3 按此顺序“属于”Blob2。
我预计有几个问题需要解决:
- 我是否可以使用字符串参数名称反映可用类型以及如果可能的话如何做到这一点
- 是否有一种巧妙的方法可以从参数列表的组合属性中进行适当的构造函数推断,或者我是否必须“手动”进行某些操作。
- 如果可能的话,我希望模型类能够接受参数 as 参数,而不是一些键和值的集合,这需要模型公开大量参数化方法在运行时,我无需显式编写它们 - 大概是为相关命名空间中可用的每个工厂方法一个。
我真正要问的是你将如何实施这样一个系统,而不是它是否从根本上可行。我对 .NET 反射没有远见或经验,无法自己想办法。希望这将是一次内容丰富的讨论。
更新:
嗯,基本上,我在实现一个简单的案例,一个玩具模型方面已经有所突破。核心逻辑是:
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:问得好。我想答案是“视情况而定”;因为我还没有决定。我想到的是能够允许用户通过简单的拖放/复制粘贴(例如)Excel数据来配置模型;并且模型通过存在的值的组合来推断用户打算添加哪些对象。理想情况下,模型可以猜测标题被省略时每个字段的含义或其他情况。但总的来说,模型在运行时而不是设计时就知道完整的参数集,但之后会被修复。
-
顺便说一句,我想要这个功能的另一个原因是程序架构的原因——关注点分离和分层功能,我希望 UI 演示者能够简单地抛出一堆模型中的值,并假设它知道如何处理它们(如果需要)。
标签: .net factory named-parameters