При создании каждого справочника генерируется класс записи справочника. Его исходным описанием служит название справочника (Name), а списком его свойств – соответствующие свойства справочника.
Например, рассмотрим создание простого справочника DictionaryName со свойствами ID, Name и ReferenceID.
Класс модели предметной области, сгенерированный по этому описанию, выглядит следующим образом:
[Table(Name = "VDICTIONARY_NAME"), Serializable] [LocalizedDisplayName(typeof(DictionaryName), "Ultima.Metadata.Classes.Resources", "DictionaryName")] public partial class DictionaryName : IDictionaryRecord, ISerializable, ICloneable, IRevertibleChangeTracking, IEditableObject, INotifyPropertyChanging, INotifyPropertyChanged { [Column(Name = "ID", CanBeNull = false, IsPrimaryKey = true)] [LocalizedDisplayName(typeof(DictionaryName), "Ultima.Metadata.Classes.Resources", "DictionaryName_ID")] public long ID { get; set; }
[Column(Name = "NAME", CanBeNull = false)] [LocalizedDisplayName(typeof(DictionaryName), "Ultima.Metadata.Classes.Resources", "DictionaryName_Name")] public string Name { get; set; }
[Column(Name = "REFERENCE_ID", CanBeNull = true)] [Browsable(true)] [LocalizedDisplayName(typeof(DictionaryName), "Ultima.Metadata.Classes.Resources", "DictionaryName_ReferenceID")] public long ReferenceID { get; set; } } |
Все классы записей справочников реализуют следующие интерфейсы:
•IDictionaryRecord – наследуется от базовых интерфейсов IEntity и IBusinessObject. Реализуется только классами записей справочников, соответственно можно получить перечень всех классов записей справочников, запросив кто реализует этот интерфейс;
public interface IDictionaryRecord : IEntity, IBusinessObject { // Возвращает развязочные таблицы, связанные с записью справочника. IKeyValueStore<string, ILinkTable> LinkTables { get; }
// Возвращает коллекции записей справочника, связанные с записью справочника. IKeyValueStore<string, IDictionaryTable> DictionaryLists { get; } } |
•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).
Информация о метаданных справочника хранится в статических полях его же класса и описывается следующим образом:
public static IClassDescriptor StaticClassDescriptor { get { return new DictionaryDescriptor { ID = 4416, Name = "DictionaryName", Caption = ResourceHelper.GetString(typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName"), Type = typeof(DictionaryName), ImplementedInterfaces = new List<string> { "IDictionaryRecord" }, TableName = "DICTIONARY_NAME", MapObjectName = "VDICTIONARY_NAME", SequenceName = "DICTIONARY_NAME_SEQ", Comments = string.Empty, Guid = new Guid("8f1a68bf-4b3b-4c07-9676-2df9373992c5"), DisplayFormat = "{ID} {Name}", IsCached = true, IsSmall = true, IsKernel = false, TransparentTranslation = false, NotificationEnabled = true, DefaultSearchProperty = "Name", ParentProperty = null, DefaultLookupProperties = new List<string> { "ID", "Name" }, FilterProperties = new List<string> { "ID", "Name" }, IconName = null, LargeIconName = null, Icon = null, LargeIcon = null, Properties = new List<DictionaryPropertyDescriptor> { new DictionaryPropertyDescriptor { ID = 4417, Name = "ID", Caption = ResourceHelper.GetString( typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName_ID"), Type = PropertyTypes.Long, ColumnName = "ID", DefaultValue = string.Empty, Comments = string.Empty, StringSize = 256, IsRequired = true, IsTranslatable = false, }, new DictionaryPropertyDescriptor { ID = 4418, Name = "Name", Caption = ResourceHelper.GetString( typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName_Name"), Type = PropertyTypes.String, ColumnName = "NAME", DefaultValue = string.Empty, Comments = string.Empty, StringSize = 64, IsRequired = true, IsTranslatable = true, }, new DictionaryPropertyDescriptor { ID = 4799, Name = "ReferenceID", Caption = ResourceHelper.GetString( typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName_ReferenceID"), Type = PropertyTypes.Long, ColumnName = "Reference_ID", DefaultValue = "-1", Comments = string.Empty, StringSize = 256, IsRequired = true, IsTranslatable = false, }, }, References = new List<DictionaryReferenceDescriptor> { new DictionaryReferenceDescriptor { ID = 2662, Name = "Reference", Caption = ResourceHelper.GetString( typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName_ReferenceID"), Type = "ReferenceDictionaryName", ThisKey = "ReferenceID", Comments = string.Empty, GetClassDescriptor = () => DictionaryName.StaticClassDescriptor, }, }, LinkTables = new List<DictionaryLinkTableDescriptor> { new DictionaryLinkTableDescriptor { ID = 3696, Name = "AnotherDictionaryName", Caption = ResourceHelper.GetString( typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName_AnotherDictionaryName"), Type = "LinkTableName", OtherKey = "DictionaryNameID", Comments = string.Empty, GetClassDescriptor = () => DictionaryName.StaticClassDescriptor, }, }, LookupProperties = new List<LookupPropertyDescriptor> { new LookupPropertyDescriptor { ID = 4968, Name = "Name", Caption = ResourceHelper.GetString( typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName_Lookup__Name"), Comments = null, }, new LookupPropertyDescriptor { ID = 4969, Name = "ID", Caption = ResourceHelper.GetString( typeof(DictionaryName).Assembly, "Ultima.Metadata.Classes.Resources", "DictionaryName_Lookup__ID"), Comments = null, }, }, Constants = new List<DictionaryConstantDescriptor> { new DictionaryConstantDescriptor { ID = 5612, Name = "ConstantName", Comments = "Constant name", Value = 1, }, }, }; } } |
Каждый генерируемый класс имеет статическое свойство StaticClassDescriptor типа IClassDescriptor. Обратившись к этому свойству, можно получить все свойства класса, на какие колонки они отображены и так далее. Дескрипторы подробно описаны в разделе Дескрипторы классов.
Каждому свойству записи справочника соответствует поле типа EditableValue<T>, где Т – один из указанных в метаданных типов:
private EditableValue<string>name; ///поле
public string Name ///свойство { get { return name.Value; } set { name.Value = value; } } |
Класс EditableValue<T> реализует следующие интерфейсы:
•ISerializable;
•ICloneable;
•IRevertibleChangeTracking;
•IEditableObject;
•IEquatable<T> – обеспечивает возможность сравнения текущего объекта с указанным объектом того же типа.
Например, при редактировании элемента справочника "Товары" (класс Goods), изменяется его название (свойство Name). Свойство IsChanged интерфейса IRevertibleChangeTracking при изменении названия товара (Goods.Name) меняется с false на true. Теперь, применив метод AcceptChanges того же интерфейса, можно подтвердить изменения или, применив метод RejectChanges, откатить их.
Также свойству может соответствовать коллекция типа DictionaryTable<T> (где Т – тип элемента коллекции). Класс DictionaryTable<T> реализует следующие интерфейсы и свойства:
•BindingList<T> – базовый класс, обеспечивает привязку к данным для форм, сортировку, фильтрацию и т.п. базовые сервисы (подробное описание класса можно найти на сайте MSDN eng/rus);
•ITypedList – обеспечивает возможность узнать тип элемента списка и его (типа) свойства (подробное описание интерфейса можно найти на сайте MSDN eng/rus);
•IRevertibleChangeTracking – обеспечивает поддержку отката изменений, реализует методы AcceptChanges, RejectChanges и свойство IsChanged;
•AddedItems – коллекция добавленных элементов;
•DeletedItems – коллекция удаленных элементов.