Let's say we have a business object, let's call it a Foo, which contains an ordered list of Bars. We pass this Foo around as XML.
We have a class which deserializes a Foo XML node (FooXMLDeserializer) which itself uses a class which deserializes the child Bar XML nodes (BarXMLDeserializer).
Now, I'm adding some functionality to the BarXMLDeserializer that maintains some state such that if FooXMLDeserializer is called on two separate Foo nodes without reseting the BarXMLDeserializer's state, the results may be invalid. BarXMLDeserializer does not know when it has processed the final Bar in a Foo.
Is there some way that I can design the BarXMLDeserializer class to communicate to developers working on consuming classes that it has state and must be reset for each Foo?
Further info:
My change solves a minor enough problem in our code that I won't be able to convince my manager to let me spend X days redesigning the whole system to nicely handle this case.
If it matters, BarXMLDeserializer keeps is state in a BarStateTracker class which is internal to it.
Programming in C#, but looking for a more general solution.
Thanks.
Expose your serializer only as a static method:
// no public constructor, etc
var deserializer = BarXMLDeserializer.CreateNew();
Then, when you have finished deserializing data, mark a field in your object. If the field is set, throw an exception if the same instance is used to deserialize more data when the deserialize method is called.
if(IsInstanceExhausted)
throw new InvalidOperationException("You must use a fresh instance.");
They'll figure it out after their first exception. In addition, mark your class as IDisposable so that code naturally uses using statements:
using(var deserializer = BarXMLDeserializer.CreateNew())
{
}
The list goes on of additional ways. ALTERNATIVELY, you could simply design your Deserializer to clear it's state or reset after a deserialization attempt, or to clear the state at the beginning of a deserialization attempt.
Related
The Situation:
I have a ViewModel bound to a Settings View, where the user is supposed to enter a lot of personalized settings and should be able to save them as presets and load them. For this the ViewModel holds Collections of preset data models which themselves hold different properties, class objects and so on.
The plan is to achieve saving all the presets by xml serialization and deserialization of the whole ViewModels.
The Code / The Problem
From the Constructor of the ViewModel I call the following method:
private void InitializePresetsFromFile()
{
if (!File.Exists(Info.GetDefaultColorPalettePresetsXml()))
{
SetupNewEmpty();
SerializePresets(Info.GetDefaultColorPalettePresetsXml());
}
else
{
DeserializePresets(Info.GetDefaultColorPalettePresetsXml());
}
}
So the Method checks if the file holding the preset exists - if it doesn't it should setup an empty preset and save it to a newly created file, otherwise it should load the preset from the existing file.
The serialization process works fine, however since I serialize to this there is a problem with deserializiation:
private void DeserializePresets(string path)
{
XmlSerializer deserializer = new XmlSerializer(typeof(LinearAxisColorPresetsViewModel));
TextReader reader = new StreamReader(path);
object obj = deserializer.Deserialize(reader);
LinearAxisColorPresetsViewModel XmlData = (LinearAxisColorPresetsViewModel)obj;
reader.Close();
VolumePresetList = XmlData.VolumePresetList;
WaveShapePresetList = XmlData.WaveShapePresetList;
VolumePresetSelectedIndex = XmlData.VolumePresetSelectedIndex;
WaveShapePresetSelectedIndex = XmlData.WaveShapePresetSelectedIndex;
}
The problem here is, that since I'm calling the method InitializePresetsFromFile() directly from the constructor, the deserializer calls himself in an never ending loop resulting in an stackoverflow error.
So, the most simple solution should be to use another constructor with a parameter, where I call InitializePresetsFromFile(), right? The problem here is that the ViewModel class is directly instantiated within the xaml of the corresponding View:
<UserControl.Resources>
<ResourceDictionary>
<vm:LinearAxisColorPresetsViewModel x:Key="vm" />
</ResourceDictionary>
</UserControl.Resources>
This posts second answer states that convention is, that constructors called from XAML should be parameterless and I want to stick to that.
The question:
The question is simply how to go about this problem according to best practice. Since this is my first attempt on serialization and deserialization I fear, that I'm a bit on the wrong path here. My feeling is that only data model classes should be serialized. My ViewModel holds two ObservableCollection of such classes, however I want to serialize the complete collections as well as other properties within the ViewModel such as the selected index.
You have indeed reached a point where you have to decide how to continue. What you are doing now is not going to work. Both the XML serializer and XAML uses the default constructor in this case. You can't make it serve two purposes here.
My advice would be to create a class that mirrors the properties from your view model which you use to deserialize the XML file. This class only needs the properties, nothing more.
If the view model class is actually a static, you could use a locator class to bind it to.
First of all, you shouldn't call the InitializePresetsFromFile method in a class' constructor. The constructor must be as fast as possible and should not cause side effects. Reading a file in constructor is a bad practice: you can't create an instance of your class without accessing the file system. This means your code is not testable, it is error-prone (e.g. did you think about sudden UnauthorizedAccessExceptions?), and it is slow.
Instead, create a public method that deserializes the data from the file. This will break your endless recursion.
How to call that method?
Do you really need your LinearAxisColorPresetsViewModel instance in the resource dictionary? If not, just assign the deserialized instance to the DataContext property of your view.
If you do need that, create in your view-model an ICommand e.g. InitializeCommand that uses the above mentioned method to initialize the internal state from a file; execute that command on app startup/view show-up etc. You could use e.g. InvokeCommandAction for the Loaded event for that.
public abstract class Unit
{
public abstract List<Move> allowedMoves{get;}
}
public class Javelineer : Unit
{
public List<Move> allowedMoves =>
new List<Move> {Move.Impale, Move.JavelinThrow, Move.ShieldBlock};
}
public class Dragon : Unit
{
public List<Move> allowedMoves =>
new List<Move> {Move.BreatheFire, Move.Swipe, Move.Bite, Move.Devour, Move.TailBash};
}
The X:
Given the above code, if and how can I retrieve the allowed moves of a given unit without necessarily instantiating a new object?
I know I can retrieve the property with this code:
typeof(Javelineer).GetProperty("allowedMoves")
But if and how can I retrieve the definition of this property?
The Y:
The client (web browser) must send the game server the player's unit. This includes the unit's type and moves this unit is able to perform (4 out of all available; similarily to Pokemon).
While the validation (of course) is performed on the server, the browser still needs to get a list of available unit types and allowed moves.
In order not to duplicate code, I would like to avoid hard-coding this data in Javascript.
Having read some excellent SO questions & answers I think I can retrieve all available units with code similar to this:
Assembly.GetExecutingAssembly().GetTypes().Where(
type => type.BaseType == typeof(Unit)
).Select(type => type.Name).ToList()
I'd call this code on server startup, cache the result and send the cached result to every connecting client, because I have feeling this code is likely expensive to call.
But how can I retrieve the list of allowed moves?
You have a couple of options, but TL;DR: Construct the object instance and read the property.
In any case, here are some options, creative minds might be able to find a couple more even.
Construct the instance, read the property.
This is your best option code-wise because it will be easy to understand, maintain, bugfix.
Rewrite the code to allow for easy detection of the values using reflection
One way to do this would be to use attributes, tagging the property or object with the legal moves. However, to avoid having the bug that the attributes does one thing, the code another, you might have to change the code to use the attributes as well, which would be a performance hit.
Additionally, reading those attributes would likely construct many more objects than your original object.
Use mono.cecil or some other IL-inspection library to decode the code of the property getter and finding the construction of that list, extracting the values being added to the list. You would essentially either have to dumb down the code of that property to be on par with what you have right now (and never allow it to become more complex) or basically simulate execution of code.
This is like constructing a flotilla of space warships with enough firepower to demolish a local starsystem, just to kill an ant.
Bottom line, construct the object instance, read the property.
I have an C# object that hold a big list (10-100MB) and some other properties. I want to serialize the object, but I don't want to serialize the list. is there any easy way to do that?
Thanks!
Since it is tagged xml, this could be as simple as adding [XmlIgnore] to the appropriate property:
[XmlIgnore]
public List<Foo> Items {get;set;}
Then just use XmlSerializer as normal.
If it needs to be controllable (sometimes yes, sometimes no) then an alternative is to add:
public bool ShouldSerializeItems() {
// your logic here
}
This pattern is recognised by many serializers, XmlSerializer included.
If you mean by serialization loading the object from database, then I can recommend NHibernate, you simply mark, you want to enable lazy-loading on the List and your object will return, with Items set to null (and if you are still in transaction, Items will load, after and only after attempting to access it; if you are out of transaction already, you will get a nullPointer exception I think)... but basically, Lazy-loading in any its kind is certainly a principle, you should keep an eye on.
EDIT: missed the tags, shame on me
I've done a lot of serialization development lately, mostly for sending objects over sockets, but I've run into an interesting question: Is it possible to send just a few of the properties from an object through a serializer?
My envisioned scenario is this: You have some sort of "state" object for each client, consisting of many properties (strings, ints, bools, etc). When your client first connects, the entire state object is serialized via an Xml or Binary serializer, and sent over the socket, to be recreated on the other side. Now both client and server have identical state objects. Your server then needs to change the state, and does so by simply setting one of the state object's property. The socket (either hooked to the state's events, or part of the state object itself) could synchronize the two states by reserializing the entire object, but it seems like a single "property change" object would do.
Obviously, this could be implemented manually. But it seems like a serializer should be able to serialize just a single property, and apply it like a patch on the other side. Does anyone know if this is possible, or would I have to write the entire thing from scratch?
With XmlSerializer (and protobuf-net, for a binary equivalent, since protobuf-net adopts most of XmlSerializer's patterns) you could do this by having a method:
public bool SouldSerializeFoo() {
return fooIsDirty;
}
public string Foo {get;set;}
for each property Foo - but you'd need to maintain the "what is dirty" manually in your own code (perhaps in the set). Lots of work; I've done a diffing serializer in the past - it was a real PITA, to be honest. I should also note that the [XmlIgnore] public bool FooSpecified {get{...} set{...}} pattern does the same thing, but for what you want, ShouldSerialize* is more appropriate.
As an addition to Marc's answer, here's the MSDN docs on the ShouldSerialize* methods
The current system that I am working on makes use of Castle Activerecord to provide ORM (Object Relational Mapping) between the Domain objects and the database. This is all well and good and at most times actually works well!
The problem comes about with Castle Activerecords support for asynchronous execution, well, more specifically the SessionScope that manages the session that objects belong to. Long story short, bad stuff happens!
We are therefore looking for a way to easily convert (think automagically) from the Domain objects (who know that a DB exists and care) to the DTO object (who know nothing about the DB and care not for sessions, mapping attributes or all thing ORM).
Does anyone have suggestions on doing this. For the start I am looking for a basic One to One mapping of object. Domain object Person will be mapped to say PersonDTO. I do not want to do this manually since it is a waste.
Obviously reflection comes to mind, but I am hoping with some of the better IT knowledge floating around this site that "cooler" will be suggested.
Oh, I am working in C#, the ORM objects as said before a mapped with Castle ActiveRecord.
Example code:
By #ajmastrean's request I have linked to an example that I have (badly) mocked together. The example has a capture form, capture form controller, domain objects, activerecord repository and an async helper. It is slightly big (3MB) because I included the ActiveRecored dll's needed to get it running. You will need to create a database called ActiveRecordAsync on your local machine or just change the .config file.
Basic details of example:
The Capture Form
The capture form has a reference to the contoller
private CompanyCaptureController MyController { get; set; }
On initialise of the form it calls MyController.Load()
private void InitForm ()
{
MyController = new CompanyCaptureController(this);
MyController.Load();
}
This will return back to a method called LoadComplete()
public void LoadCompleted (Company loadCompany)
{
_context.Post(delegate
{
CurrentItem = loadCompany;
bindingSource.DataSource = CurrentItem;
bindingSource.ResetCurrentItem();
//TOTO: This line will thow the exception since the session scope used to fetch loadCompany is now gone.
grdEmployees.DataSource = loadCompany.Employees;
}, null);
}
}
this is where the "bad stuff" occurs, since we are using the child list of Company that is set as Lazy load.
The Controller
The controller has a Load method that was called from the form, it then calls the Asyc helper to asynchronously call the LoadCompany method and then return to the Capture form's LoadComplete method.
public void Load ()
{
new AsyncListLoad<Company>().BeginLoad(LoadCompany, Form.LoadCompleted);
}
The LoadCompany() method simply makes use of the Repository to find a know company.
public Company LoadCompany()
{
return ActiveRecordRepository<Company>.Find(Setup.company.Identifier);
}
The rest of the example is rather generic, it has two domain classes which inherit from a base class, a setup file to instert some data and the repository to provide the ActiveRecordMediator abilities.
I solved a problem very similar to this where I copied the data out of a lot of older web service contracts into WCF data contracts. I created a number of methods that had signatures like this:
public static T ChangeType<S, T>(this S source) where T : class, new()
The first time this method (or any of the other overloads) executes for two types, it looks at the properties of each type, and decides which ones exist in both based on name and type. It takes this 'member intersection' and uses the DynamicMethod class to emil the IL to copy the source type to the target type, then it caches the resulting delegate in a threadsafe static dictionary.
Once the delegate is created, it's obscenely fast and I have provided other overloads to pass in a delegate to copy over properties that don't match the intersection criteria:
public static T ChangeType<S, T>(this S source, Action<S, T> additionalOperations) where T : class, new()
... so you could do this for your Person to PersonDTO example:
Person p = new Person( /* set whatever */);
PersonDTO = p.ChangeType<Person, PersonDTO>();
And any properties on both Person and PersonDTO (again, that have the same name and type) would be copied by a runtime emitted method and any subsequent calls would not have to be emitted, but would reuse the same emitted code for those types in that order (i.e. copying PersonDTO to Person would also incur a hit to emit the code).
It's too much code to post, but if you are interested I will make the effort to upload a sample to SkyDrive and post the link here.
Richard
use ValueInjecter, with it you can map anything to anything e.g.
object <-> object
object <-> Form/WebForm
DataReader -> object
and it has cool features like: flattening and unflattening
the download contains lots of samples
You should automapper that I've blogged about here:
http://januszstabik.blogspot.com/2010/04/automatically-map-your-heavyweight-orm.html#links
As long as the properties are named the same on both your objects automapper will handle it.
My apologies for not really putting the details in here, but a basic OO approach would be to make the DTO a member of the ActiveRecord class and have the ActiveRecord delegate the accessors and mutators to the DTO. You could use code generation or refactoring tools to build the DTO classes pretty quickly from the AcitveRecord classes.
Actually I got totally confussed now.
Because you are saying: "We are therefore looking for a way to easily convert (think automagically) from the Domain objects (who know that a DB exists and care) to the DTO object (who know nothing about the DB and care not for sessions, mapping attributes or all thing ORM)."
Domain objects know and care about DB? Isn't that the whole point of domain objects to contain business logic ONLY and be totally unaware of DB and ORM?....You HAVE to have these objects? You just need to FIX them if they contain all that stuff...that's why I am a bit confused how DTO's come into picture
Could you provide more details on what problems you're facing with lazy loading?