locked
HealthRecordItem Factory RRS feed

  • Question

  • Hey All,

     I have a question regarding the creation of HealthRecordItem classes. We have a "mapping" library that is mapping the HealthVault Records to internal types and vice versa.

    Mapping of Health Vault records to our types has been handled and it works fine. However the reverse operation (custom types to Health Record Items) is causing some problems because of a lack of a factory class.

    I want to be able to "dynamically" generate a HealthRecord Item based on a Dictionary entry.

    Code Block

    Guid healthRecordItemTypeID = GetFromMapperForCurrentInternalType();
    HealthRecordItem item = HealthRecordFactory.CreateHealthRecordItem(healthRecordItemTypeID);
    PopulateItemFromCurrentObject(item);



    Obviously the titem typeID can be a Medication/Weight Measurement or any other type id. Although I could make heavy use of reflection (no default constructors on some HealthRecordItemTypes) to generate the items on the fly, I want to ask if there's already a way to accomplish this in the SDK.

    Thanks,
    Burag
    Thursday, November 15, 2007 9:56 PM

Answers

  • Although we have quite a bit of a codebase that works with the current interface, it looks like we'll need to change it Smile Thanks a lot for your help Eric.

    Regards,
    Burag
    Friday, November 16, 2007 7:59 PM

All replies

  • Burag,

     

    Just to make sure I understand, you are trying to write general code that will take one of your types and create the analogous HealthVault type from it.

     

    I have a couple of thoughts on that.

     

    First, to answer your question, there is no direct way to do that in the SDK. But I'm not sure how it would work even if you did have a factory method. For example, even if you were able to create an instance of Height, you'd still need custom code to get the height value into that instance, or you could do a reflection-based mapping approach. 

     

    I might be missing something about your scenario, however.

     

    Second, if your goal is to take one of your types and copy it over to healthvault, there is another option, though I'm not sure if it's more or less work.

     

    An SDK type like Height is really just a convenience class that gives you a nicer way to deal with the object, but if you want, you can deal with it purely from an XML perspective. So, if I wanted to add a Height object to the store but not use the Height class, I could write the following:

     

    string heightXml = @"<height><when><date><y>2007</y><m>11</m><d>15</d></date><time><h>14</h><m>10</m><s>15</s></time></when><value><m>1.98836235003004</m></value></height>";

    XmlDocument doc = new XmlDocument();

    doc.LoadXml(heightXml);

    HealthRecordItem height = new HealthRecordItem(Height.TypeId, doc);

    PersonInfo.SelectedRecord.NewItem(height);

     

    (I used XmlDocument in this case, but XPathDocument is a lighter-weight choice)

     

    I figured out the XML from looking at the TypeSpecificData property on a height instance that I fetched back. Obviously, on more complex data types it could take a considerable amount of work to create the xml.

     

    Hope that helps.

     

     

    Thursday, November 15, 2007 11:30 PM
  • Eric,

     Thanks for the timely reply. I actually have a dozen classes that handle specific type mappings. For example Microsoft.Health.ItemTypes.Medication to CustomMedication (my assembly) and vice versa.

    I also have a central point of entry to these assemblies where I get a bunch of "BaseTypes" such that I need something like follows:

    Code Block

    List<BaseType> myCollectionOfBaseTypes = GetThemFromSomewhere();
    foreach(BaseType b in myCollectionOfBaseTypes)
    {
          // Get the "HealthRecordItemType" that maps to my own custom internal type.
          Type t = GetCorrespondingHealthVaultTypeForMyCustomType(b);
          // Dynamically set the assembly name that implements the mapping interface.
          string strOutsideAssemblyName = GetCorrespondingMapperAssemblyFromBaseType(b);

          // Create an instance of appropriate HealthRecordItem.
          HealthRecordItem item = (HealthRecordItem)Activator.CreateInstance(t);

         // Create an instance of the mapper.
         Type tMapper = Type.Load(strOutsideAssemblyName);
         // Get a pointer to the mapper interface.
         IMapper mapper = (IMapper)Activator.CreateInstance(tMapper);

         // Call the assembly that will do the mapping.
         mapper.Map(item, b);
     
         myHealhtRecordItemCollection.Add(item);
       
    }

    // Save the collection to Health Vault (myHealthRecordCollection)
    .....



    I don't really want to go back to XML but if there is no way to do the above then I might need to bite the bullet and create a long method that will create the HealthRecordItems according to the baseType (it's just tedious!) Smile

    Thanks for your response.
    Burag

    Friday, November 16, 2007 3:35 PM
  • Could you modify your approach so that instead of calling

     

    mapper.Map(item, b);

     

    you could call.

     

    HealthRecordItem item = Mapper.Create(b);

     

    That would put the code to create a type next to the mapping code which already has to know about that type.

     

    Friday, November 16, 2007 5:26 PM
  • Although we have quite a bit of a codebase that works with the current interface, it looks like we'll need to change it Smile Thanks a lot for your help Eric.

    Regards,
    Burag
    Friday, November 16, 2007 7:59 PM