问题
I'm having a difficult time finding information on how to elegantly serialize ActiveRecord objects.
We would like to use XML as the format because we need to output our objects in such a way that another program will be able to feasibly parse them.
XML-Serialization is usually very easy and straightforward to implement, but the problem comes when trying to serialize an object returned from the ActiveRecord database. The database returns a proxy class of the object, the type of which cannot be explicitly anticipated via the [XmlInclude]
attribute.
For example:
public class Foo : ActiveRecordLinqBase<Foo>
{
public virtual string Bar{get;set;}
public virtual int FooId{get;set;}
public Foo(string bar)
{
Bar = bar;
}
public static void FooSerializeExample()
{
Foo tehFoozor = new Foo("omgFoo!");
tehFoozor.SaveAndFlush();
int id = tehFoozor.FooId;
//...
//Assume new ActiveRecord session.
XmlSerializer serializer = new XmlSerializer(typeof(Foo));
Foo tehFoozorToSerialize = Foo.Find(id);
using(Stream stream = File.OpenWrite("tehFoozor.xml"))
{
serializer.Serialize(stream, tehFoozorToSerialize); //Will fail
}
}
}
When serializing here, we'll get a message:
"The type FooProxy2e2de24df9be42909d13a67fdb00b981 was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."
where the Proxy type will be completely unpredictable (at least to my knowledge).
As a temporary solution, my team has stubbed out each AR object's properties into interfaces. Then, we implemented "Container" objects for each, which are essentially Xml-Serializable non-AR versions of the objects. Considering the fact that we currently have 18 different AR objects which are serialized, that's 36 additional files in our solution! Something (everything) tells me this is a bad solution, but I've not been able to find a better way.
We also tried using the Soap Formatter, but since ActiveRecrodLinqBase<> isn't "marked as serializable", this was a dead end also.
回答1:
Fetch everything you need eagerly, then use AutoMapper to map it to DTOs and serialize those DTOs.
The proxy error you're getting suggests that your DTOs are actually using NHibernate's proxied collections, when they should be using plain List<T>
or arrays instead. Make sure you use ToList()
or similar.
Also, you don't need to use interfaces to map DTOs.
回答2:
Try the DataContractSerializer.
Its equivalent of [XmlInclude] is [KnownType], which includes a version that can dynamically supply the type to include the first time the type is reflected. See http://msdn.microsoft.com/en-us/library/ms730167.aspx
Also, I think (though not 100% sure) that .NET4.0 will include a "Type Mapper" feature in the DataContractSerializer which specifically makes scenarios like this easier.
If you do end up trying the DCS and will run into questions, post as comments to this answer and I'll try to answer them.
来源:https://stackoverflow.com/questions/1539118/c-sharp-castle-activerecord-how-to-elegantly-xml-serialize-activerecord-objec