How can I convert an XML structure to a defined object? - c#

I am accessing a service and I get returned an object in the form of (for example)
Car _car = _service.FetchCar(carId)
Car.Color
Car.Tires.Right.Front
Car.Tires.Left.Front
Car.Tires.Right.Back
Car.Tires.Left.Back
Car.Spoiler
etc, etc...you get the idea. My application is recieving many different objects with many differen structures. What I'd like to do is to be able to have one method that would be able to take one type of object and map it to another...
What I don't want to have to do is to manually map all the fields from the service object to my domain object with every object type
for example
If I get a Car object from the service I'd like to map it to my own Car object and if I get a Table object I'd like to map it to my own table object
any ideas?

Have a look at tools like AutoMapper to handle these "copy all fields from object A to object B" scenarios.
AutoMapper will automatically copy all fields with identical names from one instance to the other, and you can set up additional rules to allow copying of fields where the names don't match (and you can also define custom converters if you need to convert data types along the way).
Very useful, very helpful!
Marc

Related

Using a subset of an object in different services

lets say that I have a system that heavily relies on a single object, for example a Person.
I have a storage service (service 1) that handles basic CRUD operations for Person, and saves this person in mongo.
But this Person object is very big and nested, it has a lot of properties, some of them are irrelevant for some of the other services.
For example we have service 2 that gets a Person object from the storage service and renders it in the ui, he only cares about some of the properties and doesnt need the whole big and nested Person object.
And we have service 3 that gets a Person object from the storage service and needs a diff subset of properties then service 2.
We are using .Net so everything is strongly typed.
The straightforward solution is to define a subset of the Person class in each of the services, and have some converter that converts the Person object to the object this service needs (removing irrelevant properties). But some services need the exact Person object besides 5-10 properties, and as I said the Person is a huge nested object.
What is the best practice for this scenario? We dont want to re define a new “”mini person” for every service with its relevant properties because that feels like huge code duplication + creating heavy dependencies between every service and the storage service.
But we are using .Net so we have to have some strongly typed object, otherwise we wont be able to make any manipulations on the object we received from the storage service, considering we dont want to use it as plain json and just traverse the keys.
We thought of 2 solutions:
First is to use the same Person object between all services. Each service will get the person obj, so any manipulation it needs and then serialize it with a custom serializer that removes some keys from the json, this way the one whos getting the response will get only the relevant props.
Second is to add some kind of annotations to the props that says “if the req came from service 2 then do json ignore” and just dont serialize this prop in the return value from the storage service. But this makes the storage service notnot isolated and simple, and this way in service 2 we again cant deserialize and manipulate the obj cause we dont have a strongly typed “mini person”, so we have to use the json.
Is there a better known solution for this situation?
And again, this is under the assumption that the Person obj is huge and requires a lot of work do re define it again and again and will create heavy dependencies.
Thanks.
If we're talking best practices, maybe this Person object shouldn't have gotten so big to begin with. You can always break nested arrays and objects in their own separate files, entities or mongo collection.
But as it stands, maybe you could use dynamic or IDictionary<string, object> instead of creating a type Person and mapping every single strongly typed field in that class.
using System.Dynamic;
var person_from_database = person_repository.GetById(1);
dynamic person_result = new ExpandoObject();
person_result.name = person_from_database.fullname; //declare whatever properties your services need
person_result.first_address = person_from_database.addresses[0]; //even nested arrays and objects
person_result.name = person_result.name.ToUpper(); //modify values if needed
return Ok(person_result); //return whatever, no mapping
More details here!

group some properties in properties tab in visual studio

I want to have some properties like this
for example I want to have System Permission and it contains properties like SMS,Line, and ...
The UI here is based on the TypeDescriptor view of the object being inspected. Grouping isn't a concept, but it does support sub-objects. The easiest way to do what you want is to simply model the group's as different types, so: have a class that represents System Permission things, with properties for SMS etc. Attributes like [DisplayName(...)] can be used to tweak display with spaces etc. You'd then have an instance of your type as a property on the object being edited.
Everything here can be done without changing the model, but that requires custom type descriptors, which is hard to do and not particularly exciting. Changing the object model is qucker and easier.

Querying RavenDB with a reflected type

I load types dynamically through reflection, instantiate the classes, fill them with data and then save them to RavenDB. They all implement an interface IEntity.
In the RavenDB UI, I can see the classes correctly displayed and the meta data has the correct CLR type.
Now I want to get the data back out, change it and then save it.
What I'd like to do
I have the System.Type that matches the entity in RavenDB's CLR meta data, assuming that's called myType, I would like to do this:
session.Query(myType).ToList(); // session is IDocumentSession
But you can't do that, as RavenDB queries like so:
session.Query<T>();
I don't have the generic type T at compile time, I'm loading that dynamically.
Solution 1 - the Big Document
The first way I tried (for a proof of concept) was to wrap all the entities in a single data object and save that:
public class Data {
List<IEntity> Entities = new List<IEntity>();
}
Assuming the session is opened/closed properly and that I have an id:
var myDataObject = session.Load<Data>(Id);
myDataObject.Entities.First(); // or whatever query
As my types are all dynamic, specified in a dynamically loaded DLL, I need my custom json deserializer to perform the object creation. I specify that in the answer here.
I would rather not do this as loading the entire document in production would not be efficient.
## Possible solution 2 ##
I understand that Lucene can be used to query the type meta data and get the data out as a dynamic type. I can then do a horrible cast and make the changes.
Update after #Tung-Chau
Thank you to Tung, unfortunately neither of the solutions work. Let me explain why:
I am storing the entities with:
session.Store(myDataObject);
In the database, that will produce a document with the name of myDataObject.GetType().Name. If you do:
var myDataObject = session.Load<IEntity>(Id);
Then it won't find the document because it is not saved with the name IEntity, it is saved with the name of the dynamic type.
Now the Lucene solution doesn't work either but for a slightly more complex reason. When Lucene finds the type (which it does), Raven passes it to the custom JsonDeserialiser I mentioned. The custom Json Deserialiser does not have access to the meta data, so it does not know which type to reflect.
Is there a better way to retrieve data when you know the type but not at compile time?
Thank you.
If you have an ID (or IDs):
var myDataObject = session.Load<IEntity>(Id);
//change myDataObject. Use myDataObject.GetType() as you want
//....
session.SaveChange();
For query, LuceneQuery is suitable
var tag = documentStore.Conventions.GetTypeTagName(typeof(YourDataType));
var myDataObjects = session.Advanced
.LuceneQuery<IEntity, RavenDocumentsByEntityName>()
.WhereEquals("Tag", tag)
.AndAlso()
//....

Setting base class object to derived class object

I have four classes. Person, NaturalPerson (Inherits from Person), GroupFamilyMember(Inherits from NaturalPerson), QuotationHolder(Inherits from GroupFamilyMember).
They all share the same ID.
My problem is the following one:
There is a method that returns an existing NaturalPerson(stored in DB) object based on a document number. Then, I have to create a QuotationHolder, and I want that QuotationHolder object to contain the retrieved NaturalPerson object.
The issue, is that I can´t cast the object like this (I know the reason):
QuotationHolder quotationHolder = (QuotationHolder) naturalPerson;
I tried creating a new QuotationHolder object and setting its values with the naturalPerson´s object values using reflection.
But as I lose the reference to the retrieved object, when I want to save in cascade, NHibernate gives me the following exception:
a different object with the same identifier value was already associated with the session
I guess that its trying to save the object as a new one.
Just to consider:
The IDs are set using the HILO Algorithm.
The mappings cannot be changed, neither the classes.
The way I understand your question, this is what you are trying to do:
class A {}
class SubA : A {}
A instance = new A();
instance = magic-convert-object-to-different-type<Sub>(instance);
Changing the class (type) of an existing object cannot be done in C#. NHibernate is designed to translate between the object model and a relational storage model, and therefore has no support for this either.
There are other possible models to handle when objects need to be perceived as changing classes, for instance the State design pattern. Or maybe you should reconsider if this is really what you want at all - perhaps the additional data that the subclasses hold should be in "sibling-objects", that reference back to the basic person class.
It is also possible to use plain SQL to convert the data that represents the NaturalPerson into data that represents a QuotationHolder - when asked to load the converted data, NHibernate will now to instantiate a QuotationHolder instead.

Storing list of parameters in database

I want to store list of parameters (that will define how document is going to be generated on the web page) in data base.
There is a number of item (or document) types, each type has a different set of parameters that vary (each type has it's own parameters).
Is it a good idea to store all parameters (key-value) as JSON in table's column?
Otherwise I would have to create Parameter Table for every Type and column for every parameter (10-30 params for every type).
A note: I am not going to search by parameters or something like that.
I will load the the JSON string (if I'll choose JSON), serialize it to Object and apply them on document as usual.
Since you have no requirement of searching by parameters, To me Json seems to be more robust because you will have Object ready with information when you Deserialize it. where as if you store it in columns and table you will have to initialize class members yourself. It will also have performance benifit as there will be only one column to fetch based on your document type.
Conclusion go with Json data in Database
Sounds like you should have a look at http://sisodb.com. However, it does support querying, but that is something you could turn-off and only rely on GetById.

Categories

Resources