i want to write my own serialisation (xml and binary do not fit for me,
i want "a more ADO" way)
so i defined an interface:
interface ISerializeData
{
DataTable GetDataSchema();
DataTable SerializeData();
object DeserializeData(DataTable data);
}
now i do not want to create an instance of an object to let
me get the schema for that object.
And: DeserializeData should return an instance, not use an instance.
Therefore i think it should be also static. (okay, it can initialize
an instancce from a datatable...)
Any ideas? How can i model that? static is not allowed in
interfaces and my classes already inherit from another abstract
base class.
Any ideas appreciated!
that issue is why the other serializer utilize attributes as they allow you to provide metadata about how the class is to be stored with out forcing you to deal with the implementation of the class itself.
Maybe I'm wrong, but this is really more a task for a utility class. Take DeserializeData, for instance. Somewhere in your code you decide which type you're going to construct. In your proposed code you would choose the type and call its static method. Now what? Would each type have its own code to do the serialization? You'd probably end up creating some class doing all the work, to stay DRY. So you might as well have one DeserializeData method in a utility class, like:
public static T DeserializeData(DataTable data)
where T : new
{
var T = new T();
.... // Set properties
}
In this method you'd probably get the data schema.
Maybe SerializeData() could be an instance method, but that too would delegate its work to some utilty class.
Please let me know if I completely misunderstood your question.
Related
I'm refactoring a class that represents the data in some XML. Currently, the class loads the XML itself and property implementations parse the XML every time. I'd like to factor out the XML logic and use a factory to create these objects. But there are several 'optional' properties and I'm struggling to find an elegant way to handle this.
Let's say the XML looks like this:
<data>
<foo>a</foo>
<bar>b</bar>
</data>
Assume both foo and bar are optional. The class implementation looks something like this:
interface IOptionalFoo
{
public bool HasFoo();
public string Foo { get; }
}
// Assume IOptionalBar is similar
public class Data : IOptionalFoo, IOptionalBar
{
// ...
}
(Don't ask me why there's a mix of methods and properties for it. I didn't design that interface and it's not changing.)
So I've got a factory and it looks something like this:
class DataFactory
{
public static Data Create(string xml)
{
var dataXml = new DataXml(xml);
if (dataXml.HasFoo())
{
// ???
}
// Create and return the object based on the data that was gathered
}
}
This is where I can't seem to settle on an elegant solution. I've done some searching and found some solutions I don't like. Suppose I leave out all of the optional properties from the constructor:
I can implement Foo and Bar as read/write on Data. This satisfies the interface but I don't like it from a design standpoint. The properties are meant to be immutable and this fudges that.
I could provide SetFoo() and SetBar() methods in Data. This is just putting lipstick on the last method.
I could use the internal access specifier; for the most part I don't believe this class is being used outside of its assembly so again it's just a different way to do the first technique.
The only other solution I can think of involves adding some methods to the data class:
class Data : IOptionalFoo, IOptionalBar
{
public static Data WithFoo(Data input, string foo)
{
input.Foo = foo;
return input;
}
}
If I do that, the setter on Foo can be private and that makes me happier. But I don't really like littering the data object with a lot of creation methods, either. There's a LOT of optional properties. I've thought about making some kind of DataInitialization object with a get/set API of nullable versions for each property, but so many of the properties are optional it'd end up more like the object I am refactoring becomes a facade over a read/write version. Maybe that's the best solution: an internal read/write version of the class.
Have I enumerated the options? Do I need to quit being so picky and settle on one of the techniques above? Or is there some other solution I haven't thought of?
You can think of such keywords as virtual/castle dynamic proxy/reflection/T4 scripts - each one can solve the problem on a slightly different angle.
On another note, this seems perfectably reasonable, unless I misunderstood you:
private void CopyFrom(DataXml dataXml) // in Data class
{
if (dataXml.HasFoo()) Foo = dataXml.Foo;
//etc
}
What I did:
I created a new class that represented a read/write interface for all of the properties. Now the constructor of the Data class takes an instance of that type via the constructor and wraps the read/write properties with read-only versions. It was a little tedious, but wasn't as bad as I thought.
I have a couple of classes in my system
//this was not made an Interface for some WCF reasons
public abstract class BaseTransmission
{
protected internal abstract string Transmit();
//other common properties go here
}
And a few child classes like
public class EmailTransmission : BaseTransmission
{
//This property is added separately by each child class
public EmailMetadata Metadata { get; set; }
protected internal override string Transmit()
{
//verify email address or throw
if (!Metadata.VerifyMetadata())
{
throw new Exception();
}
}
}
Elsewhere, I have created a method with signature Transmit(BaseTransmission transmission). I am calling this method from another part of my code like this:
TransService svc = new TransService();
EmailTransmission emailTrans = new EmailTransmission(); // this inherits from BaseTransmission
svc.Transmit(emailTrans);
This solves my purpose. But usually when I see examples of polymorphism, I always see that the reference type is base class type and it points to an instance of child class type. So usually in typical examples of polymorphism
EmailTransmission emailTrans = new EmailTransmission();
will usually be
BaseTransmission emailTrans = new EmailTransmission();
I cannot do this because EmailTransmission EmailMetadata is different from lets say FaxMetadata. So if I declare the reference to be of BaseTranmission type and point it to an instance of EmailTranmission type, I lose access to the EmailMetadata property of the EmailTransmission.
I want to know whether what I am doing above is a misuse of polymorphism and whether it 'breaks' polymorphism in some way. And if it is abusing polymorphism, whats the right way to do this.
This is perfectly valid. The polymorphic pattern is used in the TransService service Transmit method.
It works with a class that can be morphed in one or more classes.
The fact that you declare the variable using the base class or the derived class is up to you and depends on your specific case.
That should be completely fine. Within the transmit method the object is referenced as BaseTransmission, the "downcasting" is therefore less obvious.
(had this as comment beforehand, but this should really be an answer)
Well, this is perfetly valid case: as you use base class type like a base parameter in the
TransService.Trasmit method.
The only thing which looks strange is:
protected internal abstract string Transmit();
do you really need protected and internal ?
If yes, just skip this notion.
Generally you would prefer using base type
BaseTransmission emailTrans = new EmailTransmission();
This keeps you abstraction clean and helps you with Don't Repeat Yourself. This will be useful in the following scenario: suppose a user can select how she/he can be contacted (email, fax, text). When you need to send something you just have a single method that takes BaseTransmission object and parameters, say BaseParameter.
Note: if it looks, as if there is not much code can be shared, you can define an interface ITransmitter and use it to show that a class can send something, like:
ITransmitter transmitter = new EmailTransmission();
What you are doing is absolutely correct and should work without issue. Passing a child class to a function/method that takes the base class should not be an issue.
However, regarding your example here:
This solves my purpose. But usually when I see examples of polymorphism, I always see that the reference type is base class type and it points to an instance of child class type. So usually in typical examples of polymorphism
EmailTransmission emailTrans = new EmailTransmission();
will usually be
BaseTransmission emailTrans = new EmailTransmission();
This is done if BaseTransmission is an interface or abstract class and you then need to construct a specific version of BaseTransmission. Sometimes if you don't need the extra components some people like to use this to keep their code clean as well. The most common usage of this is seen with generics such as when you want to create a List for example, but need to implement a specific version os List such as ArrayList or LinkedList
I have a function that at the moment takes a Type variable. This function sticks it in a list and such and eventually needs will create a class of that type.
Right now I do that with
object o=MyType.GetConstructors()[0].Invoke(new object[0]);
which is pretty hacky and also will not work in medium trust due to reflection(I think). Is there a better way of doing this without reflection?
The Type is defined this way as part of a function. I need the class to be created "lazily" because it may not be created in the application if it's not needed. I use it for example like
AddToList(typeof(Whatever));
Note, I'm open to suggestions on changing the function calling. I just need the object to be created lazily and for to store the type(or however to create an object of the type) in a list.
I've considered lambdas but I'm not sure they'd work here.
Using Generics:
public void Method<T>() where T : class, new()
{
//code
T t = new T();
}
Using Activator (still reflection, meh):
object t = Activator.CreateInstance(yourTypeVariable);
Personally, I would prefer the first solution due to being strongly typed. However, you should be aware that both methods only allow for parameterless constructors. If you need to pass parameters, you will need reflection or expression trees.
Another alternative solution is FormatterServices.
object instance = FormatterServices.GetUninitializedObject(typeof(MyClass));
Note that the instance is created without any fields/properties initialized, even you have
class MyClass
{
public int i = 99;
public Object o = new object();
}
instance.i will be 0 and instance.o will be null. It's quite hard to provide a pure non-reflection solution(because always you need to call o.GetType()). This solution essentially serialize the object and then deserialize it to an object, so you don't need to use reflection to call its constructor. But there is still reflection when serialization/deserialization.
After further research on lambdas, I've discovered they will give me a much more elegant solution and it does not use reflection
So I used in my list definition
public delegate MyBaseType TypeCreator();
...
public TypeCreator Creator;
and in my function call, a simple and elegant lambda:
AddToList(()=>{return new MyType();});
I think this is quite a bit cleaner than my reflection method because it allows putting parameters into the constructor, and a few other reasons outside of the scope of this question. (It just goes with my project well)
Reading some article about singleton, I stopped at the point saying: "Do not allow to crate copy of existing instance".
I realized that I do not know how would I do that! Could you tell me, please, how could I copy existing instance of class?
And the second one: deserializaition. How it could be dangerous?
And for both - how to deny creating copies or deserialization?
Thanks
There are objects with something like a Clone or a Copy method. The idea behind it that it will take the current values of the object and make a new one. The defeats the purpose of a singleton object, because suddenly someone can create a second copy of it.
Another possible way of creating a copy of the object, would be to serialize the object and then de-serialize it to create another copy. So you probably want to mark the singleton object as not serializable.
Using serialization/deserialization, you could store the object somewhere and then restore it. That way, you will have two objects. Any changes made to the singleton in the meantime would not be reflected in your new copy.
Afterwards, when you now try to get/set something using the singleton object, you might change it in/get it from the one object or the other. Obviously that can cause all sorts of (sometimes very hard to debug) problems.
EDIT: To create a singleton in C#, see the explanation at http://www.yoda.arachsys.com/csharp/singleton.html
As for serialization: You have to explicitely enable it by including the SerializableAttribute. So simply don't mark your class with it. Note that there is no NonSerializableAttribute for classes, only for fields. It is used when you enabled serialization, but want to deny it for certain parts of the class.
EDIT2: To deny XML-serialization, you could implement IXmlSerializable on the class. Then simply either have empty implementations or throw exceptions from the member methods.
As has already been mentioned:
You don't want to make a singleton serializable or copy/clone-able because then you can make more than one object, which defeats the purpose of the singleton.
To prevent serialization in c# is easy - don't mark the class as [Serializable]
To prevent copying/cloning of your singleton you could try changing it to a static class so that can't be instantiated (in the normal way) if that's practical. I'm not sure if the class is technically a singleton any more then.
Another way (probably better) is detailed in Item 13 of Bill Wagner's Effective C#. i.e. using a static constructor and making your singleton a read only property of your static class.
Example:
public class SingletonExample
{
private static readonly SingletonExample singleInstance
static SingletonExample()
{
singleInstance = new SingletonExample();
}
public static SingletonExample Instance
{
get { return singleInstance; }
}
private SingletonExample()
{
}
}
There are a few things to look out for, like Kevin mentioned any sort of .Clone() or .Copy() methods. If your building the class your self, then be carful with the .MemberwiseClone() method as it will make shallow copies of the object.
As far as serialization. Preventing general serialization can be done by not tagging [SerializableAttribute()] to you class. I'm not sure there is a way to prevent XmlSerialzation, directly. But there are a few things you could do to prevent this if your building the class.
If you're building the class, and you do not provide a default constructor then the XmlDeserializer will not work as it uses the default constructor to rebuild the object. I belive this funcitonality has changed in 4.0 however, so you may want to look more into that. Using the [XmlIgnore] Attribute on yoru fields and properties will render the serialzation useless as well.
The important part here is that the person trying to do this understand it shouldn't be done, not that it can't. If someone really wants to do serialization/deserialization on your class, then you can't stop all avenues as he can implement his own serialzation/deserialization of your object. Also serialzation of singletons is sometimes intended such as the cases of application settings or custom settings. The intent is to inform somehow the person trying to serialize/deserialize not to do so.
Is it somehow possible to use the XmlSerializer to deserialize its data into an existing instance of a class rather than into a new one?
This would be helpful in two cases:
Easily merge two XML files into one object instance.
Let object constructer itself be the one who is loading its data from the XML file.
If the is not possible by default it should work by using reflection (copying each property after the deserialisation) but this would be an ugly solution.
Basically, you can't. XmlSerializer is strictly constructive. The only interesting thing you can do to customize XmlSerializer is to implement IXmlSerializable and do everything yourself - not an attractive option (and it will still create new instances with the default constructor, etc).
Is xml a strict requirement? If you can use a different format, protobuf-net supports merging fragments into existing instances, as simply as:
Serializer.Merge(source, obj);
I think you're on the right track with the Reflection idea.
Since you probably have a wrapper around the XML operations anyway, you could take in the destination object, do the deserialization normally into a new object, then do something similar to cloning by copying over one by one only the properties holding non-default values.
It shouldn't be that complex to implement this, and it would look to consumers from the rest of your application just like in-place deserialization.
I hit the same problem a few weeks ago.
I put a method Deserialize(string serialized form) in the ISelfSerializable interface that an entity class of mine implemented. I also made sure the interface forced the class to have a default constructor.
In my factory I created an object of that type and then deserialized the string into it.
This is not thread safe thing to do... But you can do:
[Serializable]
public class c_Settings
{
static c_Settings Default;
public static SetExistingObject(c_Settings def)
{
Default = def;
}
public string Prop1;
public bool Prop2;
public c_Settings()
{
if (Default == null)
return;
MemberInfo[] members = FormatterServices.GetSerializableMembers(typeof(c_Settings));
FormatterServices.PopulateObjectMembers(this, members, FormatterServices.GetObjectData(Default, members));
}
}
This way you feed your object to deserialiser and deserialiser only overwrites whatever is written in .xml.