Should classes be able to save and load themselves via XML?
So mainly I'm looking for a best practices sort of answer here. I have a system which is basically a set of rules, some data, and a manager to make sure the data follows the rules. Pretty simple. I'm trying to figure out the best way of handling saving and loading of the rules. For a first attempt, I have an interface called IRule which all the rules inherit.
interface IRule
{
/* all rules inherit this */
string RuleName {get;}
}
interface IRuleTypeA : IRule
{
/* Type A Rules */
double[] Data;
}
interface IRuleTypeB : IRule
{
/* Type B Rules */
double[,] Data;
}
public static class IRuleExtensions
{
XElement AsXml(this IRuleTypeA ruleA)
{
//format my data my way and return an XElement representation
return new XElement(...);
}
XElement AsXml(this IRuleTypeB ruleB)
{
//format my different data in a different way and return an XElement
return new XElement(...);
}
XElement AsXml(this IRule rule)
{
object definition = null;
if(rule is IRuleTypeA)
definition = (rule as IRuleTypeA).AsXml();
else if(rule is IRuleTypeB)
definition = (rule as IRuleTypeB).AsXml();
return new XElement("RuleDefinition", new XAttribute("name", rule.RuleName),
definition);
}
}
So here, I'm putting the saving functionality into the class being saved. I was about to implement a similar loading mechanism that will take each element and construct a rule. Before I do that, I wanted to see if there were best practices about this. Should I instead create a separate system which would take a rule, interrogate it, then save that to XML and use a factory-type system to consume the Xml to construct the objects back?
interface RuleToXmlAdaptor
{
XElement AsXml(IRule rule);
IRule Fr开发者_开发技巧omXml(XElement element);
}
class RuleAToXmlAdaptor : RuleToXmlAdaptor
{
XElement AsXml(IRule rule) { return AsXml(rule as IRuleTypeA); }
XElement AsXml(IRuleTypeA rule);
}
I go back and forth between these methods not really sure when to use one or the other or if there's a better solution still.
I do not want to use Serialization because the file type is likely to change continuously and I can manage the compatibility fairly simply this way.
I don't think the class itself should know anything about how it can be serialized. That violates the single-responsibility principle. Think about the case where tomorrow a new awesome serialization format comes out, say SoupML. If you let someone outside the object take care of the serialization, then it should be really easy to make your system work well with SoupML and you won't even have to change the existing rule models.
Ideally only those units that explicitly consume XML should be aware of XML, this way your system can be made out of units that wouldn't care about the format but only about the interfaces. Somewhere later they will be told which serializer/deserializaer to use (Inversion of Control). Having it this way also supports open-close principle. You won't have to pry open stuff for modification, but it will be open for extension.
I think you have to start looking at xml attributes that can be used on your class and properties that can allow you easily to serialize your class object to xml file and deserialize it again when need.
I wouldn't do it this way because it ties your hands, though in the short term it might be more convenient. Instead of XElement
, why not have the interface expose Dictionary<string,object>
. Then, you can have key-value pairs (with well-known value types, like String
and Dictionary<string,object>
). This way, unit testing will be easier and you can use a more efficient format if you so choose.
interface RuleSerializer
{
Dictionary<string,object> AsDictionary(IRule rule);
IRule FromDictionary(Dictionary<string,object> data);
}
精彩评论