При создании каждого типа документа генерируется класс этого документа. Исходным названием служит название типа документа (Name) +"Document", а списком его свойств – соответствующие свойства типа документа.
Например, рассмотрим создание простого типа документа DocType со свойствами AgentID и Amount и подтипом DocSubType.
Класс модели предметной области, сгенерированный по этому описанию, выглядит следующим образом:
[Table(Name = "VD_DOCTYPE"), Serializable] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument")] public partial class DocTypeDocument : IDocument, IEntity, ISerializable, ICloneable, IRevertibleChangeTracking, IEditableObject, INotifyPropertyChanging, INotifyPropertyChanged, IEquatable<DocTypeDocument> { [Column(Name = "AGENT_ID", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_AgentID")] public long AgentID { get; set; }
[Column(Name = "AMOUNT", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Amount")] public decimal Amount { get; set; }
[Column(Name = "DELETED", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Deleted")] public bool Deleted { get; set; }
[Column(Name = "ID", CanBeNull = false, IsPrimaryKey = true)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_ID")] public long ID { get; set; }
[Column(Name = "CREATOR_ID", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_CreatorID")] public long CreatorID { get; set; }
[Column(Name = "COMMENTS", CanBeNull = true)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Comments")] public string Comments { get; set; }
[Column(Name = "TOTALS_LIST", CanBeNull = true)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_TotalsList")] public string TotalsList { get; set; }
[Column(Name = "DOCTYPE_OBJ_ID", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_TypeID")] public long TypeID { get; set; }
[Column(Name = "SUBTYPE_OBJ_ID", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_SubtypeID")] public long SubtypeID { get; set; }
[Column(Name = "VERSION", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Version")] public long Version { get; set; }
[Column(Name = "DESCRIPTION", CanBeNull = true)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Description")] public string Description { get; set; }
[Column(Name = "CREATION_DATE", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_CreationDate")] public DateTime CreationDate { get; set; }
[Column(Name = "TRANSACTION_DATE", CanBeNull = false)] [Browsable(true)] [LocalizedDisplayName(typeof(DocTypeDocument), "Ultima.Metadata.Classes.Resources", "DocTypeDocument_TransactionDate")] public DateTime TransactionDate { get; set; } } |
Помимо свойств ArticleID и Amount сгенерированный класс содержит описания системных свойств, которые создаются автоматически для каждого типа документа.
Все классы документов реализуют следующие интерфейсы:
•IDocument – наследуется от базовых интерфейсов IEntity и IBusinessObject. Реализуется только классами документов, соответственно можно получить перечень всех классов документов, запросив кто реализует этот интерфейс:
public interface IDocument : IEntity, IBusinessObject { long TypeID { get; set; } long SubtypeID { get; set; } long CreatorID { get; set; } DateTime CreationDate { get; set; } DateTime TransactionDate { get; set; } string Description { get; set; } string Comments { get; set; } string TotalsList { get; set; } bool Deleted { get; set; } long Version { get; set; }
// Возвращает табличные части документа. IKeyValueStore<string, ITablePart> TableParts { get; } } |
•IEntity – базовый для классов всех объектов интерфейс;
•ISerializable – обеспечивает поддержку эффективной сериализации (подробное описание интерфейса можно найти на сайте MSDN eng/rus);
•ICloneable – обеспечивает поддержку клонирования объекта (подробное описание интерфейса можно найти на сайте MSDN eng/rus);
•IRevertibleChangeTracking – обеспечивает поддержку отката изменений (подробное описание интерфейса можно найти на сайте MSDN eng/rus), реализует:
▪метод AcceptChanges – сбрасывает состояние объекта в неизмененное, принимая изменения;
▪метод RejectChanges – восстанавливает неизмененное состояние объекта, отменяя изменения;
▪свойство IsChanged – возвращает значение true, если содержание объекта было изменено с момента последнего вызова метода AcceptChanges, в противном случае – значение false;
•IEditableObject – предоставляет функциональные возможности транзакционного редактирования в стиле DataRowView (подробное описание интерфейса можно найти на сайте MSDN eng/rus), реализует методы:
▪BeginEdit – начинает редактирование объекта;
▪CancelEdit – уничтожает изменения, выполненные после последнего вызова метода BeginEdit;
▪EndEdit – подтверждает изменения, выполненные с момента последнего вызова метода BeginEdit;
•INotifyPropertyChanging – событие для поддержки привязки данных к элементам управления WinForms (подробное описание интерфейса можно найти на сайте MSDN eng/rus);
•INotifyPropertyChanged – событие для поддержки привязки данных к элементам управления WinForms (подробное описание интерфейса можно найти на сайте MSDN eng/rus);
•IEquatable<T> – обеспечивает возможность сравнения текущего объекта с указанным объектом того же типа.
Информация о метаданных справочника хранится в статических полях его же класса и описывается следующим образом:
public static IClassDescriptor StaticClassDescriptor { get { return new DocumentDescriptor { ID = 4111, Name = "DocTypeDocument", Caption = ResourceHelper.GetString(typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument"), Type = typeof(DocTypeDocument), ImplementedInterfaces = new List<string> { "IDocument" }, TableName = "D_DOCTYPE", MapObjectName = "VD_DOCTYPE", Comments = string.Empty, Guid = new Guid("19e78552-a4e9-4c6d-8727-3ecfa7a7f6c6"), DisplayFormat = "{Description}", FilterProperties = new List<string> { "ID", "AgentID", "Amount", "Version", "TotalsList", "TypeID", "CreationDate", "SubtypeID", "CreatorID", "Deleted", "TransactionDate", "Description", "Comments" }, IconName = null, LargeIconName = null, Icon = null, LargeIcon = null, Properties = new List<DocumentPropertyDescriptor> { new DocumentPropertyDescriptor { ID = 4112, Name = "ID", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_ID"), Type = PropertyTypes.Long, ColumnName = "ID", DefaultValue = string.Empty, Comments = "Identity", StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 5223, Name = "AgentID", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_AgentID"), Type = PropertyTypes.Long, ColumnName = "AGENT_ID", DefaultValue = "-1", Comments = string.Empty, StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 5801, Name = "Amount", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Amount"), Type = PropertyTypes.Decimal, ColumnName = "AMOUNT", DefaultValue = string.Empty, Comments = string.Empty, StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4119, Name = "Version", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Version"), Type = PropertyTypes.Long, ColumnName = "VERSION", DefaultValue = string.Empty, Comments = "Document version", StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4122, Name = "TotalsList", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_TotalsList"), Type = PropertyTypes.String, ColumnName = "TOTALS_LIST", DefaultValue = string.Empty, Comments = "Totals list", StringSize = 256, IsRequired = false, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4113, Name = "TypeID", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_TypeID"), Type = PropertyTypes.Long, ColumnName = "DOCTYPE_OBJ_ID", DefaultValue = "-1", Comments = "Document type identity", StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4117, Name = "CreationDate", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_CreationDate"), Type = PropertyTypes.DateTime, ColumnName = "CREATION_DATE", DefaultValue = string.Empty, Comments = "Creation date", StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4114, Name = "SubtypeID", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_SubtypeID"), Type = PropertyTypes.Long, ColumnName = "SUBTYPE_OBJ_ID", DefaultValue = "-1", Comments = string.Empty, StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4115, Name = "CreatorID", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_CreatorID"), Type = PropertyTypes.Long, ColumnName = "CREATOR_ID", DefaultValue = "-1", Comments = "Document creator", StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4116, Name = "Deleted", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Deleted"), Type = PropertyTypes.Boolean, ColumnName = "DELETED", DefaultValue = "false", Comments = "Is document deleted", StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4118, Name = "TransactionDate", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_TransactionDate"), Type = PropertyTypes.DateTime, ColumnName = "TRANSACTION_DATE", DefaultValue = string.Empty, Comments = "Transaction date", StringSize = 256, IsRequired = true, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4120, Name = "Description", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Description"), Type = PropertyTypes.String, ColumnName = "DESCRIPTION", DefaultValue = string.Empty, Comments = "Description", StringSize = 256, IsRequired = false, IsMultilanguage = false, }, new DocumentPropertyDescriptor { ID = 4121, Name = "Comments", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Comments"), Type = PropertyTypes.String, ColumnName = "COMMENTS", DefaultValue = string.Empty, Comments = "Comments", StringSize = 256, IsRequired = false, IsMultilanguage = false, }, }, References = new List<DocumentReferenceDescriptor> { new DocumentReferenceDescriptor { Name = "Agent", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Agent"), Type = "Agent", ThisKey = "AgentID", Comments = string.Empty, GetClassDescriptor = () => Agent.StaticClassDescriptor, }, new DocumentReferenceDescriptor { Name = "Creator", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Creator"), Type = "User", ThisKey = "CreatorID", Comments = "Document creator", GetClassDescriptor = () => User.StaticClassDescriptor, }, new DocumentReferenceDescriptor { Name = "Type", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Type"), Type = "DocumentType", ThisKey = "TypeID", Comments = "Document type", GetClassDescriptor = () => DocumentType.StaticClassDescriptor, }, new DocumentReferenceDescriptor { Name = "Subtype", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Subtype"), Type = "DocumentSubtype", ThisKey = "SubtypeID", Comments = "Document subtype", GetClassDescriptor = () => DocumentSubtype.StaticClassDescriptor, }, }, Subtypes = new List<DocumentSubtypeDescriptor> { new DocumentSubtypeDescriptor { ID = 5231, Name = "DocSubType", Caption = ResourceHelper.GetString( typeof(DocType).Assembly, "Ultima.Metadata.Classes.Resources", "DocType_Subtype__DocSubType"), Comments = string.Empty, }, TableParts = new List<DocumentTablePartDescriptor> { new DocumentTablePartDescriptor { ID = 5229, Name = "Articles", Caption = ResourceHelper.GetString( typeof(DocTypeDocument).Assembly, "Ultima.Metadata.Classes.Resources", "DocTypeDocument_Articles"), Type = "ArticleTablePartRow", OtherKey = "DocumentID", Comments = string.Empty, GetClassDescriptor = () => ArticleTablePartRow.StaticClassDescriptor, }, }, }; } |
Каждый генерируемый класс имеет статическое свойство StaticClassDescriptor типа IClassDescriptor. Обратившись к этому свойству, можно получить все свойства класса, на какие колонки они отображены и так далее. Дескрипторы подробно описаны в разделе Дескрипторы классов.
Каждому свойству документа соответствует поле типа EditableValue<T>, где Т – один из указанных в метаданных типов:
private EditableValue<int>b; ///поле public int B; ///свойство { get { return b.Value; } set { b.Value = value; } } |
Класс EditableValue<T> реализует следующие интерфейсы:
•ISerializable;
•ICloneable;
•IRevertibleChangeTracking;
•IEditableObject;
•IEquatable<EditableValue<T> – обеспечивает возможность сравнения текущего объекта с указанным объектом того же типа.
Также свойству может соответствовать коллекция типа DictionaryTable<T> (где Т – тип элемента коллекции). Класс DictionaryTable<T> реализует следующие интерфейсы и свойства:
•BindingList<T> – базовый класс, обеспечивает привязку к данным для форм, сортировку, фильтрацию и т.п. базовые сервисы (подробное описание класса можно найти на сайте MSDN eng/rus);
•ITypedList – обеспечивает возможность узнать тип элемента списка и его (типа) свойства (подробное описание интерфейса можно найти на сайте MSDN eng/rus);
•IRevertibleChangeTracking – обеспечивает поддержку отката изменений, реализует методы AcceptChanges, RejectChanges и свойство IsChanged;
•AddedItems – коллекция добавленных элементов;
•DeletedItems – коллекция удаленных элементов.