Will IModelObject support GetObject?

Jan 25, 2013 at 2:52 PM

I am considering how best to mapping state data to a given shape.  I see that IModelObject supports GetInteger, GetFloat, GetString, but my implementation will require mapping to an object type.  Do you think I should simply store my state data (which does not need to persist at all) in the shape tag property or should I leverage the SetString/GetString for example to store a key value for looking up the state of the object in a Dictionary.  Looking for some guidance with respect to the best way to leverage the business/data model concept in NShape.

Jan 28, 2013 at 10:43 AM

We try to avoid boxing/unboxing (which would be performed automatically by the .NET framework in case of GetObject()) for better performance and scalability.

To be honest, I don't can't imagine a scenario where you need a GetObject() method and therefore it's difficult to give a suitable advice.
Could you please give me an example of what you are trying to do?

Jan 28, 2013 at 2:13 PM

I can understand the performance concern and can work around managing business data associated with a given shape.  An example scenario is if I wanted a shape to represent a personal contact item.  The associated data such as name, address, state, phone number etc. could be retrieved directly getting an object associated with the shape (ie. ContactInfo).   I think I now have an design approach which will meet my implementation requirements. 

Jan 29, 2013 at 3:09 PM

I also wonder what are we supposed to do when our Model contains not only "simple" properties but "complex" ones as well. Will IRepositoryWriter / IRepositoryReader instances work correctly with arbitrary complex types?!

Recently I implemented my own RepositoryWriter (and RepositoryReader) which is able to save arbitrary Shape into a compact XML. However, today I faced a problem when Model of some certain type needed to be saved to XML as well (in my application it is rather an exception than a rule - Models are stored separately in a database). Frankly speaking, I didn't try to use my RepositoryWriter for these purposes - although properties of this Model seem to be ready for that (PropertyId constants, PropertyMappingId attributes and GetPropertyDefinitions() method are all defined). Instead, I serialized this Model to XML in a separate routine. But already after that I asked myself a question: is it good that this routine in fact duplicates all that PropertyId stuff? Should I know exactly that IEntity.SaveFields / .LoadFields works OK with complex types - I'd prefer using an "NShape-like" approach...

Jan 30, 2013 at 11:55 AM
Edited Jan 30, 2013 at 1:26 PM

@ rcunday:
As the shape cannot display such complex information anyway, you could provide a property like  

class MyModelObject {
    public string ContactInfoText {
        get  { return string.Format(
"{0} {1}", _contactInfo.ForeName, _contactInfo.LastName); }

This kind of property can be mapped using the existing ModelMappings. You could also implement IModelObject for the ContactInfo object if this suits better for your needs.


@ Commanche:
As long as your model provides a suitable set of InnerObjectPropertyDefinition, this should no problem.

    public class MyModelObject : IModelObject {
        // ...

        public static IEnumerable<EntityPropertyDefinition> GetPropertyDefinitions() {
            yield return new EntityFieldDefinition("...", typeof(string));
            yield return new EntityInnerObjectsDefinition("ContactInfo", typeof(ContactInfo).FullName,
                new string[] { "ForeName", "LastName", "Address", "ZipCode", "City", "Email", "Phone", "Mobile" },
                new Type[] { typeof(string), typeof(string), typeof(string), typeof(Int16), typeof(string), typeof(string), typeof(string), typeof(string) } );

        public void LoadInnerObjects(string propertyName, IRepositoryReader reader, int version) {
            if (propertyName == "ContactInfo") {
                // Load vertices
                while (reader.BeginReadInnerObject()) {
                    // Read point definition
                    _contactInfo = new ContactInfo();
                    _contactInfo.ForeName = reader.ReadString();
                    _contactInfo.LastName = reader.ReadString();
                    _contactInfo.Address = reader.ReadString();
                    _contactInfo.ZipCode = reader.ReadInt16();
                    _contactInfo.City = reader.ReadString();
                    _contactInfo.EMail = reader.ReadString();
                    _contactInfo.Phone = reader.ReadString();
                    _contactInfo.Mobile = reader.ReadString();
            } else if (propertyName == "...") {
                // ...
            } else base.LoadInnerObjects(propertyName, reader, version);
        public void SaveInnerObjects(string propertyName, IRepositoryWriter writer, int version) {
            if (propertyName == "ContactInfo") {
                // If you have more than one contact info, insert a loop here

            } else if (propertyName == "...") {
                // ...
            } else base.SaveInnerObjectsCore(propertyName, writer, version);

        // ...
Jan 30, 2013 at 12:23 PM

Thank You, I'll try it in my project!

Jan 30, 2013 at 2:15 PM

Excellent idea!  I'll have to try this out!  Thanks!