答案 0 :(得分:4)
如果我可以这么说,那么组织你的解决方案不应该是你最关心的问题,因为你的代码现在似乎遇到了一个更重要的问题,这可能导致许多难以发现的错误;即:
schema_obj = New Schema schema_obj.Info = New Info schema_obj.Info.Number = New Number schema_obj.Info.Number.Value = 3
你提到了依赖注入,所以我会在一般方向上写一些东西。
依赖注入非常有用,因为它可以为您构建“对象图”。也就是说,如果一个对象具有对其正常运行所需的其他对象的引用,则这些其他对象本质上是“依赖性”。 (如您所见,您的Schema
个对象每个都有Info
个“依赖关系”,而您的Info
个对象都有Number
个“依赖关系”。)DI容器(如Autofac,Unity,NInject,StructureMap或Castle)可以自动初始化对依赖项的引用。
现在再次对比你自己的代码:
schema_obj = New Schema schema_obj.Info = New Info schema_obj.Info.Number = New Number schema_obj.Info.Number.Value = 3
旁注:这种类型的代码 - 即通过遍历一系列对象访问一个属性 - 通常被称为“火车残骸”编码。我鼓励你谷歌获取"Law of Demeter" (LoD),a.k.a。“最少知识原则”,以了解为什么这是不好的做法。
基本上,您是从外部手动初始化Schema
对象的(schema_obj
)依赖项。如果每次需要Schema
对象实例时都必须执行此操作,则很容易忘记某些内容,从而导致不完整的依赖项对象图,从而导致错误(例如NullReferenceException
s)。
将初始化代码移动到类的构造函数
纠正这个问题的第一步是让Schema
自己完成这项工作。现在,生成器声明生成的类Partial
是有充分理由的,即您可以轻松地将自己的代码添加到它们中。我假设Schema
,Info
和Number
是这样的自动生成的类。因此,您可以为这些类添加自己的附加初始化代码:
Public Partial Class Schema
Public Sub New()
Me.Info = New Info()
End Sub
End Class
Public Partial Class Info
Public Sub New()
Me.Number = New Number()
End Sub
End Class
这意味着您现在可以将上述代码更改为:
schema_obj = New Schema() ' this will trigger the above constructors
schema_obj.Info.Number.Value = 3
(第二行仍然不是很好,但我必须更好地了解你的程序和领域模型,以提供有关如何改进的建议;我现在暂时离开这里。)
为什么这段代码更好?因为您的Schema
对象现在将确保它已正确初始化。现在,与以前不同,Schema
类的“用户”不再需要知道如何构造Schema
对象以使其正常工作。关于Schema
内部功能的“知识”已被移入Schema
类本身,它真正属于它; Schema
“用户”不再需要担心内部Schema
对象的外观如何。
(正是由于这个原因,第二行:schema_obj.Info.Number.Value = 3
仍然是邪恶的。这行代码对对象的内部结构做了很多假设。它应该看起来更像{{1} }。)
走向依赖注入
如果你想使用DI容器,那么为你的代码做好准备的一种方法就是按如下方式改变你的构造函数:
schema_obj.SetNumber(3)
乍一看,这似乎与我上面写的内容相矛盾:你的构造函数现在声明它们分别“需要”一个Public Partial Class Schema
Public Sub New(ByVal info As Info)
Me.Info = info
End Sub
End Class
Public Partial Class Info
Public Sub New(ByVal number As Number)
Me.Number = number
End Sub
End Class
对象或一个Info
对象。
然而,通过依赖注入 - 更具体地说,一种称为“构造函数注入”的技术 - 您实际上不必自己调用这些构造函数; DI容器将为您做到这一点:
Number
DI容器的schema_obj = dependencyInjectionContainer.Resolve(Of Schema)()
方法将自动将已指定为参数的依赖项“注入”构造函数到构造函数中。但是,这要求您先前通过“注册”它们来使DI容器知道所有相关类型。
这只是为了让您了解自己可能会走向何方。您现在可能不需要DI,但我强烈建议您至少将自己的构造函数添加到自动生成的类中,如图所示。
答案 1 :(得分:0)
根据您问题的最新更新,您似乎正在执行以下操作:
如果就是这样,我确实想知道这是否是正确的方法,或者你是不是更好地保留内存XML文档形式的一切; e.g:
Imports System.Xml
Imports <xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
…
Dim personName = "Bob"
Dim personAddress = "New York"
Dim xmlDocument =
<Schema xsi:noSchemaNamespaceLocation="./relativePathTo/yourSchema.xsd">
<Info>
<Number>3</Number>
<Person>
<PersonName><%= personName %></PersonName>
<PersonAddress><%= personAddress %></PersonAddress>
</Person>
</Info>
</Schema>
这样,构建一个完整的XML文档很容易,而且序列化到文件应该很容易。
Imports
指令导入名称空间。<%=
a VB.NET expression
=>
。