如何组织我的代码

时间:2011-08-15 19:24:34

标签: vb.net architecture

2 个答案:

答案 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容器(如AutofacUnityNInjectStructureMapCastle)可以自动初始化对依赖项的引用。

现在再次对比你自己的代码:

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是有充分理由的,即您可以轻松地将自己的代码添加到它们中。我假设SchemaInfoNumber是这样的自动生成的类。因此,您可以为这些类添加自己的附加初始化代码:

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)

根据您问题的最新更新,您似乎正在执行以下操作:

  1. 采用XML Schema并从中生成VB.NET类。
  2. 构建对象并填写一些数据(属性值)。
  3. 将所有内容序列化为XML。
  4. 如果就是这样,我确实想知道这是否是正确的方法,或者你是不是更好地保留内存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指令导入名称空间。
    • 您可以在XML树中拥有“占位符”<%= a VB.NET expression =>
    • 您可以通过架构文件验证内联XML。