Attributes in Custom Objects
The approach to using the AOM Property model was this: I have a MetadataEntity object, which contains an attributes collection of type MetadataAttributeCollection, a collection of MetadataAttribute classes. This MetadataAttribute class has a Name, Type, and Value property, which contains the information stored as the attribute. I also include a generic method to get the strongly-typed version of the value:
public T GetValue<T>()
{
if (this.Value != null)
return (T)this.Value;
return default(T);
}
The collection is a straight-forward collection, with some validation to ensure that when adding an item, that there isn't a duplicate item (an item with the same name) already in the list. If there is, an error is thrown. To determine the name, I added a default property that takes a parameter of name, and gets the object, if found:
public MetadataAttribute this[string name]
{
get
{
foreach (MetadataAttribute attribute in this)
{
if (string.Compare(name, attribute.Name, true) == 0)
return attribute;
}
return null;
}
}
Also, for the sorting, I override the Compare method (as mentioned in my previous post), with this method:
public override int Compare(MetadataAttribute x, MetadataAttribute y)
{
return x.Name.CompareTo(y.Name);
}
This method compares the metadata by the name, and sorts them this way by default, so they appear in order by name. I also provide a generic method to get the value of a named metadata attribute, using the default property to get the metadata object by name, if it exists. If it does, then it returns the value; otherwise, null is returned.
The MetadataEntry class exposes these properties through a property, which the collection is lazy-loaded (loaded when it is referenced):
public MetadataAttributeCollection Attributes
{
get
{
if (_attributes == null)
_attributes = new MetadataAttributeCollection();
return _attributes;
}
}
However, in this instance, it is loaded in the constructor, so lazy-loading really isn't a feature. The constuctor takes the name as a parameter and assigns it to the collection:
public MetadataEntry(string name)
{
//Add the initial name attribute
this.Attributes.Add(new MetadataAttribute("Name", name));
}
Using the collection, you can create properties defined in the class, as I did for the Name property:
public string Name
{
get { return this.Attributes.GetValue<string>("Name"); }
set { this.SetAttributeValue("Name", value); }
}
This property returns the Name attribute value stored in the class; however, it isn't recommended to do this. You lose the easier maintenance approach whenever you upgrade the application this way. But, for Name, which is a common property across all objects, I did it this way. SetAttributeValue is a helper method; if the name is null, it adds the name/value to the collection; otherwise, the existing attribute value is overwritten with the new value.
These objects will be featured in the next test.