Scenario
I have a use case where I need do decompose an hierarchical object tree into a set of its constituent objects. Later on, I will also need to recompose those objects back into their original form.
Goals
My goals are as follows.
- Determine the
fastestand mostprocessorand/ormemory efficientways todecompose/recomposethe objects. (This code will process millions of objects so saving even a few ticks is useful.) - Locate any existing
librariesorexampleswhich may facilitate thisdecomposition/recompositionscenario or which may demonstrate how others have done something similar. - Compile a list of
strategies,methods, andtechniquesfordecomposinganobject hierarchy(in.NET 4.5+,.NET Core) into its elementary objects andrecomposingthose elementary objects back into an hierarchy. (Note: There is no such thing as too many ideas, too many techniques, or too many examples here.)
'Givens' / Requirements
- This functionality will be implemented in
.NET Core 1.xand above. Backwards compatibility with.NET 4.5+would be a plus. - The structure of the
object treeis not necessarily known in advance.- The
decomposition componentmust be able to work with any provided object tree.
- The
- The
object hierarchymay be many layers deep.- The
decompositionwill run recursively until it reaches the lowest level of theobject tree. Most objects (except as described below) will bedecomposed. Arraysandcollectionsmay optionally be kept intact rather than beingdecomposed. This will vary from usage to usage. I would say that generally,Arrays,Dictionaries,simple lists(e.g.lists of strings) will generally not bedecomposed.Complex lists(e.g.lists of objectswill likelydecompose.)
- The
Recompositionof object hierarchies may be full or partial.- During
recomposition, other objects may be inserted into the object hierarchy (or existing objects may be replaced) to make completely new types of objects.
Potentially Important Issues Not Yet Considered
I am still at an early stage in analyzing how to accomplish this object. (Frankly, I feel like I am flying blind here.) There are probably many important factors I have not considered. These include:
- Any potential impact of self-referencing
classes. - Implications or impact of other potential element or object types.
Resources I am Currently Reviewing
I have a reasonable idea of generally how to accomplish the decomposition and recomposition through reflection. However, I am not confident that I know how to do it well, do it efficiently, or do it in a way that properly handles every issue.
Here is a list of some of the resources I am reviewing now.
XmlSerializer- from .NET reference source http://ift.tt/2rgcoxyNewtonsoftJson- http://ift.tt/1bCBZrvMessagePack-Csharp- for .NET Core - extremely efficient. http://ift.tt/2lMsoFpProtobuf.nethttp://ift.tt/1vafO3F
Demo Class / Object Hierarchy
I have created a very simple for-demonstration-purposes-only class hierarchy which represents the types of elements I would expect to find in the object hierarchies which we will process.
These include:
ValueType- (e.g. integer) PropertyString- PropertyDateTime- PropertyCustom Class- PropertyDictionary- CollectionLists- CollectionArray- Field
There is a single base class which generates an Id of type Guid on the parent and all children.
public class EntityBase
{
public EntityBase()
{
Id = Guid.NewGuid();
}
public Guid Id { get; set; }
}
The root object in the demo hierarchy is of type Person. It contains various general properties of type string, int, and DateTime just as one would find in most any class. It also contains List and Dictionary collection classes, as an array, and a reference to single custom object.
public class Person : EntityBase
{
public Person()
{
Phones = new List<Phone>();
Addresses = new List<Address>();
Passwords = new Dictionary<string, string>();
FavoriteFood = new FoodPreference();
}
public string FirstName { get; set; }
public string LastName { get; set; }
public int Weight { get; set; }
public DateTime DateOfBirth { get; set; }
public FoodPreference FavoriteFood {get; set;}
public string[] Dogs = { "Shayna", "Sport" };
public Dictionary<string, string> Passwords { get; set; }
public ICollection<Phone> Phones { get; set; }
public ICollection<Address> Addresses { get; set; }
}
There is a collection of phone numbers.
public class Phone : EntityBase
{
public string PhoneNumber { get; set; }
}
There is a collection of postal addresses.
public class Address : EntityBase
{
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
There is a custom class with some detail on a favorite food.
public class FoodPreference : EntityBase
{
public string FoodCategory { get; set; }
public string FoodName { get; set; }
}
Just to put it all together, here is a sample method which populates the heirarchy with dummy data.
public static Person BuildPerson()
{
return new Person
{
FirstName = "Anthony",
LastName = "Gatlin",
Weight = 154, // I wish. :)
DateOfBirth = DateTime.Parse("01/01/1970"),
Phones = new List<Phone>
{
new Phone {PhoneNumber = "601-555-1212"},
new Phone {PhoneNumber = "601-555-1213"}
},
Addresses = new List<Address>
{
new Address {StreetAddress = "111 Country Rd", City = "Heidelberg", State = "MS", PostalCode = "39349"}
},
Passwords = new Dictionary<string, string>
{
{"google","googlepass" },
{"skype","skypepass" },
{"facebook","facebookpass" }
}
};
}
The sample object hierarchy can be retrieved from http://ift.tt/2rfSKl3.
Output From Sample Data
Following is a simple JSON dump of sample data generated for this hierarchy.
{ "Dogs": [ "Shayna", "Sport" ], "FirstName": "Anthony", "LastName": "Gatlin", "Weight": 154, "DateOfBirth": "1970-01-01T00:00:00", "FavoriteFood": { "FoodCategory": "Baked Goods", "FoodName": "Chocolate Cake", "Id": "0c516c4d-ff64-4b8d-bb44-b430aa8d3ce5" }, "Passwords": { "google": "googlepass", "skype": "skypepass", "facebook": "facebookpass" }, "Phones": [ { "PhoneNumber": "601-555-1212", "Id": "57bdfdcb-4232-40e4-aab8-4c6387029257" }, { "PhoneNumber": "601-555-1213", "Id": "b591afc3-6e91-4030-ad26-00beefceca43" } ], "Addresses": [ { "StreetAddress": "111 Country Rd", "City": "Heidelberg", "State": "MS", "PostalCode": "39349", "Id": "94cc5e37-db96-44b7-869a-818968d99ddd" } ], "Id": "629ae27e-17aa-49ad-823a-2cd2ebf0cb66" }
Expected Result
Once the objects have been decomposed from the object hierarchy, I will end up storing some sort of simple hierarchy which will allow me to recompose the objects.
Given the following Id Guids ...
629ae27e-17aa-49ad-823a-2cd2ebf0cb66// Person Id0c516c4d-ff64-4b8d-bb44-b430aa8d3ce5// FavoriteFood57bdfdcb-4232-40e4-aab8-4c6387029257// Phone1 Idb591afc3-6e91-4030-ad26-00beefceca43// Phone2 Id94cc5e37-db96-44b7-869a-818968d99ddd// Address Id
we may end up with a very simple JSON Hierarchy like so.
{
"Person":{
"Id":"629ae27e-17aa-49ad-823a-2cd2ebf0cb66", "FavoriteFood":{
"Id":"0c516c4d-ff64-4b8d-bb44-b430aa8d3ce5" }, "Phone":[
{
"Id":"57bdfdcb-4232-40e4-aab8-4c6387029257" }, {
"Id":"b591afc3-6e91-4030-ad26-00beefceca43" } ], "Address":[
{
"Id":"94cc5e37-db96-44b7-869a-818968d99ddd" } ] } }
Each object with dependencies will have its own one-level dependency tree.
The above format is just an example, and I am completely open to (read desperately seeking) ideas on better ways to do this.
Each of the elementary objects will actually be serialized to JSON or MsgPack. We will be able to fully or partially reassemble the objects from the hierarchy when required.
Thank You!
I am really looking for any guidance, recommendations, advice, ideas, tips, examples, code snippets, libraries, or anything else you can offer that will help me to accomplish this task efficiently.
Thank you so very much, in advance, for your help! It is extremely appreciated.
Aucun commentaire:
Enregistrer un commentaire