Как организовать мой код - PullRequest
       8

Как организовать мой код

2 голосов
/ 15 августа 2011

У меня есть автоматически сгенерированный файл классов со многими частичными классами (автоматически сгенерированный из схемы xsd). Я использую VS2010 и VB.NET. Я хочу создать объекты всех частичных классов, как это

Dim schema_obj As Schema
schema_obj = New Schema
schema_obj.Info = New Info
schema_obj.Info.Number = New Number
schema_obj.Info.Number.Value = 3

Для всех свойств в разных классах (например,

schema_obj.Info.Number.Value
schema_obj.Info.Birthday.Value
schema_obj.Info.Colour

Я должен написать

schema_obj.Info.Number = New Number
schema_obj.Info.Birthday = New Birtday
schema_obj.Info.Colourr = New Colour

У меня есть одна функция, которая создает все эти объекты, и таким образом я заполняю объект схемы данными.

Как лучше организовать мой код? А как насчет внедрения зависимости? Где я должен поставить свою функцию? На бизнес уровне?

Заранее спасибо

UPDATE:

Спасибо за все комментарии и ваш дополнительный ответ! Я очень ценю это! Я разрабатываю часть и бизнес-приложение. Приложение используется для регистрации данных лиц, выставления счетов, учета и так далее. Часть, которую я разрабатываю, - это система отчетности перед властью через сервисы wcf. Со своей стороны я буду использовать VB.NET, но остальные части системы разработаны в VB6. Мы используем сервер SQL, и почти вся бизнес-логика находится на стороне сервера. Поскольку я привык использовать VB6, трудно понять все вещи ООП, которые мне нужно помнить, чтобы писать код так, как он должен быть. В своей части приложения я получаю схему xsd из органа и автоматически генерирую файл класса схемы из файла xsd с помощью xsd.exe. Я вижу, что это гораздо лучшее решение, которое вы предлагаете, но когда после прочтения вашего ответа я посмотрел на свой автоматически сгенерированный файл классов, я увидел, что у каждого частичного класса есть строка MyBase = New в конструкторе. Я могу использовать это таким образом, как вы предлагаете? Извините, что не понял этого раньше! Если я правильно понимаю поведение MyBase, я могу написать

Dim Number = New Number
Number.value = 3

и конструктор Number вызовет конструктор Info, а конструктор Info вызовет конструктор Schema. И я могу написать

Dim PersonName = New PersonName
PersonName.Value = Bob

Dim PersonAdress = New PersonAdress
PersonAdress.Value = New York

вместо

schema_obj.Info.Person.PersonName = New PersonName
schema_obj.Info.Person.PersonName.value = Bob

Но все же мне нужно создать много объектов в моей функции. Как я могу сделать это лучше?

И в конце своей функции я хочу проанализировать объект схемы в потоке памяти. Я делаю это так: Тусклый поток памяти как новый System.IO.MemoryStream Dim ser As New XmlSerializer (GetType (Schema))

ser.Serialize(memorystream, Schema_obj)

Но теперь у меня нет Schema_obj, который содержит информацию, как я могу проанализировать schema_obj (всю информацию) в потоке памяти?

ОБНОВЛЕНИЕ 2

Извините, теперь я понимаю (я думаю), и я сделал, как вы сказали, и я могу написать

Schema_obj = New Schema
Schema_obj.Info.Number.Value = 3
Schema_obj.Info.Person.PersonName = New PersonName
Schema_obj.Info.Person.PersonName.value = Bob

И мне не нужно создавать объекты в моей функции. Но вместо добавления моих собственных конструкторов MyBase позаботится о работе? И теперь я также могу сериализовать мою schema_obj.

Но можете ли вы рассказать что-нибудь еще о том, как я могу решить проблему с Schema_obj.Info.Number.Value = 3 Проект, который я делаю, является отличным шагом против vb.net и ООП для моего бизнеса. Я могу использовать инфраструктуру сущностей для своего уровня данных, и у меня может быть бизнес-логика на бизнес-уровне. Мой фронтенд будет в vb6.

ОБНОВЛЕНИЕ 3

Теперь я снова в замешательстве. Я думал, что получил, но у меня нет ... когда я пытаюсь запустить свое приложение, я получаю ошибку: ссылка на объект не установлена ​​на экземпляр объекта. Кажется, я должен написать

Dim schema_obj As Schema
schema_obj = New Schema
schema_obj.Info = New Info
schema_obj.Info.Number = New Number
schema_obj.Info.Number.Value = 3

MyBase не сделал то, что я думал, что сделал? Можете ли вы объяснить еще немного? Спасибо!

ОБНОВЛЕНИЕ 4

Спасибо за ваш ответ.

  1. Возьмите схему XML и сгенерируйте классы VB.NET из нее.
  2. Создание объектов и заполнение некоторых данных (значений свойств).
  3. Сериализация всего обратно в XML.

Это яименно то, что я делаю.Но я подумал, что мне нужно преобразовать xsd в класс, построить объекты и заполнить объекты данными, а затем сериализовать их обратно в xml.Почему лучше выбрать то, что вы предлагаете?Я новичок в этом, поэтому я ценю ваши ответы.У вас есть пример, когда это хорошее решение для преобразования xsd в объекты, как я сделал?Используемый мной xsd будет меняться раз в год, проще ли адаптировать мой код к изменениям, которые вы предлагаете?Схема xsd является более сложной, чем я показывал в моем примере, я не знаю, есть ли что-нибудь, чтобы сказать, какой метод мне нужно выбрать?

ОБНОВЛЕНИЕ 5:

Я занимаюсь разработкойприложение, где я использую сервисы wcf.Я использую веб-сервис, который предлагает организация:

1.Отправить XML-схему, заполненную данными 2.Получить список доступных веб-сервисов 3.Получить конкретную xsd-схему

Что у меня естьсделать это:

1.Получить схему xsd, сформировать полномочия и использовать этот xsd для генерации xml, заполненного данными. 2. Позвонить на веб-сервис, где я могу указать номер для конкретной схемы xsd и получитьСхема XSD взамен.Затем я могу проверить свою XML-схему по ней, прежде чем отправить ее в орган

3. Используйте веб-службу, где моя строка XML находится в свойстве строки метода службы wcf, и я отправляю файл XML

Мой xsd выглядит (почти) так:

<?xml version="1.0" encoding="iso-8859-1"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:br="http://www.br.se/or" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <!--title='Tittle' lang='E'-->
  <xs:element name="Schema">
    <xs:annotation>
      <xs:documentation>
        <br:txt br:lang="E" br:txttype="LEDE">
          <p>Some text</p>
        </br:txt>
      </xs:documentation>
      <xs:documentation>


…………………………


<xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" ref="Information"/>
        <xs:element minOccurs="0" ref="Payer"/>
      </xs:sequence>
      <xs:attribute fixed="105" name="numberr" type="xs:integer" use="required"/>
      <xs:attribute fixed="10360" name="externalnumberr" type="xs:integer" use="required"/>
            <xs:attribute fixed="Title" name="title" type="xs:string" use="optional"/>
      <xs:attribute fixed="4895" name="groupid" type="xs:positiveInteger" use="optional"/>
      <xs:attribute name="id" use="optional">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="761065">
              <xs:annotation>
                <xs:documentation>Text</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:anyAttribute/>
    </xs:complexType>
  </xs:element>
<xs:element name="Info">
    <xs:annotation>
      <xs:documentation>
        <br:txt br:lang="E" br:txttype="LEDE">
          <p>Some Text</p>
        </br:txt>
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Task">
          <xs:annotation>
            <xs:documentation>
              <br:txt br:lang="E" br:txttype="LEDE">
                <p>Some text</p>
              </br:txt>
            </xs:documentation>
          </xs:annotation>
        </xs:element>
        <xs:element ref="Year">
          <xs:annotation>
            <xs:documentation>
              <br:txt br:lang="E" br:txttype="LEDE">
                <p>Some Text</p>
              </br:txt>
            </xs:documentation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="Taskowner"/>
      </xs:sequence>
      <xs:attribute fixed="4877" name="id" type="xs:positiveInteger" use="required"/>
    </xs:complexType>
  </xs:element>
<xs:element name="TaskSpesialTask">
    <xs:annotation>
      <xs:documentation>
        <br:info br:type="some txt">1</br:info>
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="List1">
          <xs:attribute fixed="212" name="schemaid" type="xs:positiveInteger" use="required"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="List2">
    <xs:annotation>
      <xs:documentation>
        <br:info br:type="id">2</br:info>
      </xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:string">
      <xs:length value="1"/>
      <xs:enumeration value="1">
        <xs:annotation>
          <xs:documentation>
            <br:txt br:lang="E" br:txttype="LEDE">
              <p>Some text</p>
            </br:txt>
          </xs:documentation>
        </xs:annotation>
      </xs:enumeration>
      <xs:enumeration value="2">
        <xs:annotation>
          <xs:documentation>
            <br:txt br:lang="E" br:txttype="LEDE">
              <p>Some text</p>
            </br:txt>
          </xs:documentation>
        </xs:annotation>
      </xs:enumeration>
    </xs:restriction>
  </xs:simpleType>
<xs:element name="Year">
    <xs:annotation>
      <xs:documentation>
        <br:info br:type="pl">2</br:info>
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="Format">
          <xs:attribute fixed="692" name="schemaid" type="xs:positiveInteger" use="required"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="Format">
    <xs:annotation>
      <xs:documentation>
        <br:info br:type="id">6</br:info>
      </xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:gYear"/>
  </xs:simpleType>
<xs:element name="TaskOwner">
    <xs:annotation>
      <xs:documentation>
        <br:txt br:lang="E" br:txttype="LEDE">
          <p>Some Text</p>
        </br:txt>
      </xs:documentation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="TaskoOwnerNumber">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="TaskOwnerName">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="TaskOwnerAdress
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="TaskOwnerPhone">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="TaskOwnerEmail">
          <xs:annotation>  
          </xs:annotation>
        </xs:element>
      </xs:sequence>
      <xs:attribute fixed="48" name="id" type="xs:positiveInteger" use="required"/>
    </xs:complexType>
  </xs:element>
<xs:element name="TaskOwnerNumber">
    <xs:annotation>
    </xs:annotation>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="TextFormat">
          <xs:attribute fixed="21" name="id" type="xs:positiveInteger" use="required"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="TextFormat">
    <xs:annotation>
      <xs:documentation>
        <br:info br:type="id">1</br:info>
      </xs:documentation>
      <xs:documentation>
        <br:txt br:lang="E" br:txttype="F">
          <p>Wrong number</p>
        </brreg:tekst>
      </xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:string">
      <xs:length value="9"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="TaskOwner name">
    <xs:annotation> 
    </xs:annotation>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="TextFormat">
          <xs:attribute fixed="2" name="id" type="xs:positiveInteger" use="required"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:element name="TaskOwner Adress">
    <xs:annotation>
    </xs:annotation>
  </xs:element>

And so on for phone and email

 <xs:element name="Payers">
    <xs:annotation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="20000" minOccurs="0" ref="PayersInfo"/>
        <xs:element minOccurs="0" ref="PaymentTotal">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="NumberOfPayers">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
      </xs:sequence>
      <xs:attribute fixed="410" name="id" type="xs:positiveInteger" use="required"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="PayersInfo">
    <xs:annotation>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" ref="PayerBirthNumber">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="PayerNumber">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="PayerBirthDay">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="PayerName">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="PayerAdress">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="PayerPhone">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="PayerEmail">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
        <xs:element minOccurs="0" ref="PayerSum">
          <xs:annotation>
          </xs:annotation>
        </xs:element>
      </xs:sequence>
      <xs:attribute fixed="48" name="id" type="xs:positiveInteger" use="required"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="PayerBirthNumber">
    <xs:annotation>
    </xs:annotation>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="TextFormat">
          <xs:attribute fixed="2305" name="id" type="xs:positiveInteger" use="required"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="TextFormat">
    <xs:annotation>
    </xs:annotation>
    <xs:restriction base="xs:string">
      <xs:length value="11"/>
    </xs:restriction>
  </xs:simpleType>


And som on for PayerNumber, PayerBirthDay, PAYerNAMe, PayerAdress, PayerPhone, PayerEmail…..

</xs:schema>

Элементы в xsd структурированы следующим образом:

Schema 
  Info
   Year
   TaskOwner
    TaskOwnerName
    TaskOwnerAdress
    TaskOwnerPhone
    TaskOwnerEmail
    TaskOwnerNumber
 Task
    TaskSpecialTask
    TaskOrdinaryTask
    Payers
        PaymentTotal
        NumberOfPayers
        PayersInfo (list of payers)
          PayerBirtNumber
          PayerBirthDay
          PayerName
          PayerAdress
          PayerPhone
          PayerEmail

(Пожалуйста, игнорируйте, есличто-то в xsd пропущено - оно есть, чтобы я мог лучше объяснить свою проблему)

Мой вопрос: как мне сгенерировать xml на основе xsd?Я хочу сделать это для нескольких схем XSD.Разве это не хорошее решение для десериализации xsd (с xsd.exe) в класс, создания объекта этого класса и заполнения его данными, а затем сериализации объекта обратно в xml?Или это еще лучше, как вы предлагаете.Я действительно хочу учиться и делать это наилучшим образом, а не делать это самым простым способом для меня .. Я надеюсь, что это облегчит вам дать мне ответ.

Спасибо!

Ответы [ 2 ]

4 голосов
/ 15 августа 2011

Если можно так выразиться, организация вашего решения не должна быть вашей первоочередной задачей, поскольку кажется, что ваш код сейчас страдает от гораздо более важной проблемы, которая может привести ко многим трудным для поиска ошибкам; а именно это:

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

Sidenote: этот тип кода & mdash; то есть доступ к свойству путем обхода цепочки объектов & mdash; обычно упоминается как кодировка "крушение поезда". Я призываю вас поискать по «1029 *« Закону Деметры »(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 все еще злая. Эта строка кода делает много предположений о внутренней структуре ваших объектов. Вероятно, она должна выглядеть больше как schema_obj.SetNumber(3).)

На пути к внедрению зависимости

Если вы хотите использовать DI-контейнер, один из способов сделать ваш код готовым к нему - это изменить ваши конструкторы следующим образом:

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 или Number соответственно.

Однако с внедрением зависимостей & mdash; более конкретно, метод, называемый «инжекцией в конструктор» & mdash; вам на самом деле не придется вызывать эти конструкторы самостоятельно; Контейнер DI сделает это за вас:

schema_obj = dependencyInjectionContainer.Resolve(Of Schema)()

Затем метод Resolve контейнера DI автоматически "внедрит" зависимости, которые были заданы в качестве параметров для ваших конструкторов, в конструкторы. Однако для этого необходимо, чтобы вы предварительно сделали все соответствующие типы известными контейнеру DI, «зарегистрировав» их.

Это просто, чтобы дать вам представление о том, куда вы, возможно, направлялись. Возможно, вам пока не понадобится DI, но я настоятельно советую вам по крайней мере добавить свои собственные конструкторы в автоматически сгенерированные классы, как показано.

0 голосов
/ 16 августа 2011

Судя по последним обновлениям вашего вопроса, вы делаете следующее:

  1. Возьмите схему XML и сгенерируйте из нее классы VB.NET.
  2. Сборкаобъекты и заполните некоторые данные (значения свойств).
  3. Сериализуйте все обратно в XML.

Если это так, я задаюсь вопросом, правильный ли это подход, или если выне было бы лучше хранить все в форме XML-документа в памяти;Например:

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=> в своем дереве XML.
  • Вы можете проверить встроенный XMLпо вашему файлу схемы.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...