XmlSerializer do not serialize readonly fields, readonly properties (only with getter), private fields etc. In addition it will not serialize the object if the class does not have a parameterless constructor. My questions:
AFAIK these problems arise because private (and readonly) fields can not be accessed (and changed) while deserializing. But what if I will not deserialize? Don't I have an option for this?
Because of the same reason (deserialization concerns), it does not serialize the object if the class does not have a parameterless constructor. But when I add a private parameterless constructor it works fine. How?
I do not like to add a parameterless constructor to every class, and make all fields public and non-readonly just to be able to serialize it. For now I am throwing an exception in the private parameterless constructor to prevent the usage. Is there an attribute for constructors which tells the compiler that only authorized calls can be made to that constructor? If not at least I would like to mark it with an attribute which throws the exception if it is called.
That's quite a good question, and I'll try my best to answer:
I believe the reason for the setter as well as the getter is that it's generally assumed if you've only got a getter, then it implies it's not an instance property, it's something that is derived. That would imply if you were to deserialize it (I know you're not doing this) then you could derive this value by setting all the other fields, and therefore serialization doesn't need to care about it.
The reason the parameterless constructor is required is because the type will be created using Reflection. Probably through a call like Activator.CreateInstace(type). This requires a parameterless constructor for the instance to be created, although it probably doesn't matter if it's public or private.
The reason the instance is required is so the fields on it can then be populated with the data retrieved from the XML.
You'll need this constructor, however you could add the ObsoleteAttribute to ensure that it's not called manually, or do as you're doing and make it private.
[Obsolete(true)]
public Foo()
{
}
One way of working around some of these issues may be to implement the IXmlSerializable interface manually, then you have a finer control over serialization but will still need that parameterless constructor.
Related
I just read http://blog.gurock.com/articles/creating-custom-exceptions-in-dotnet/
I don't know when it is written. It says:
"Since C# unfortunately doesn’t inherit constructors of base classes, this new type only has the standard constructor with no parameters and is therefore relatively useless."
This says the same in 2010: C#: inheriting constructors
Is this still true?
EDIT: Following on from answers, I'm sure there would be a way around the default parameterless constructor. Are there other reasons for lack of constructor inheritance?
Constructors have never been inheritable in the entire lifetime of the C# language. That hasn't changed in C# 5.0: at the end of section 1.6.7.1 of the C# 5.0 spec, it still says:
Unlike other members, instance constructors are not inherited, and a class has no instance constructors other than those actually declared in the class. If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided.
So it still holds true today, and I imagine it will remain so in the foreseeable future.
You have to explicitly call the constructor of the base class, unless the base class defines a default constructor. So yes they are not inherited.
Which sometimes lead to a bunch of boiler plate code where you do nothing than pass arguments from one constructor to another
public class NegativArgument : Exception {
public NegativeArgument() : this("The number given was less than zero"){}
public NegativeArgument(string message) : this(message,null){}
public NegativeArgument(string message, Exception inner) : base:(message,inner){}
}
but what if you had an Exception type that should always have the same message? how would you solve that if the constructors were inherited? The exception class has a constructor that accepts a message so creating a new Exception type would in that case get that constructor too, not inheriting constructors makes it easy
public class NegativArgument : Exception {
public NegativeArgument() : base("The number given was less than zero"){}
}
If the base class does not have a default constructor you will have a compile error if you do not explicitly call a base class constructor.
Constructors are not inherited in C#.
If they were, then every class would have a default parameterless constructor (because all classes derive from Object and Object has a default parameterless constructor).
Many classes should only be constructed with specific values; this would be impossible to ensure if every class had a default parameterless constructor.
You should call them explicitly the constructor of the base classes. They are not inheritable.
Didn't change anything about them.
Check out : Constructors (C# Programming Guide)
From the spec §1.6.7.1:
Unlike other members, instance constructors are not inherited, and a
class has no instance constructors other than those actually declared
in the class. If no instance constructor is supplied for a class, then
an empty one with no parameters is automatically provided.
http://msdn.microsoft.com/en-us/library/ms228593.aspx
This answer is based upon the section "Constructors are not inherited" near the bottom of this entry on Jon Skeet's blog.
Summary
There are many cases in which a derived class may require information beyond that contained in the base class. Jon gives the example of the FileInfo class which requires additional information to be well-defined. Namely, that of the file for which info is to be provided
Any suggested 'fix' for this would entail overriding things in a way that prevents constructing such derived objects using the inherited constructors. However, knowingly requiring derived classes to override their base classes in a way that makes them more restrictive goes against best practice. (see: this question for Jon's discussion of the Liskov Substitution principle and the importance of being able to use derived classes wherever their base can be used.)
Additionally, from just a maintenance perspective, forcing manual override of constructors would make it difficult to reason about future behavior should the base class constructors change, and would entail having to always check, and often modify, any derived classes when new constructors are added to the base. Even a few of these would be problematic; but in cases where there are dozens or more such classes (and derived classes of those classes, etc.), maintenance and QA will quickly become a nightmare.
L2SQL generates entities with a default a parameterless constructor. This CANNOT be changed as it is needed to materialise the object.
However, if my object can only be created with certain values initialised how would I go about hiding the parameterless constructor so that a consumer only sees a constructor with parameters?
1) I can create another partial class of the same name and add my new constructor there but the consumer now simply has two options to create an instance of my class. The parameterless constructor is still visible.
2) Use interfaces. It is not possible to create an interface that defines constructors.
How do people approach this as it looks like an issue that would occur a lot.
If I understand you correctly, you want to prevent other users of the class from constructing one from the parameterless constructor, but still allow Linq2SQL to use it (as it must do so).
Luckily you are wrong when you say the default parameterless constructor cannot be changed. If you change the constructor of a Linq2SQL entity class to be private, then it will still be called by Linq2SQL as it uses reflection, and it is possible to call a private constructor if you use reflection. (Incidentally, other changes to the constructor can also be done with Linq2SQL).
Of course, the other users of the class can also use reflection to call that private constructor and create a class in a private state, but that is true of all .NET classes (and indeed applies elsewhere - e.g. it's often not hard to usurp the privacy of C++ classes, though there is no implementation-independent guarantee either way). But then it's pretty much always possible to use reflection to mess a class up; encapsulation is a mechanism to ensure correctness, not security. (But security restrictions on what code can use reflection then builds security on top of that less guarantee).
Is there a way to initialize virtual automatic property without using a constructor ?
or should i just make a private field ?
Virtual or not, you need a constructor. Or it will have the default-value for it's type.
Because it is not good to call a virtual member in constructor
Correct, you will have to step carefully. The normal rules do apply. To be safe you would design your property so that it doesn't need initialization or only initialize it in derived constructors where either the class or the property is sealed.
Note that there will be plenty of cases where automatic properties makes little or no sense.
In the case of a virtual automatic property, I would say that the initialization part makes this a problem, and would remove the "automatic" part and create a backing field.
Of course, since base constructors are called before descendant constructors, if a base constructor initializes the property to the wrong value, a descendant constructor has a chance to rectify that before construction of the object is final.
Am I the only person that wants this? It seems to be something that could reasonably have been provided for any class with a public parameterless constructor. Now having to instantiate these properties inside the constructor of the class that uses them somewhat obviates the convenience of automatic properties.
I would want to be able to specify the degree of thread safety required. In particular, do you need locking code to be emitted?
Indeed that might be useful, but it is what it is. There is no sign of this in C# 4.0, so you'll just have to use either a constructor or a field (and manual property implementation).
Re your "for any class with a public parameterless constructor" - actually, I'd assume that any implementation would be directly comparable to field initializers, so would work regardless of the constructor composition.
I'm writing code to do Xml serialization. With below function.
public static string SerializeToXml(object obj)
{
XmlSerializer serializer = new XmlSerializer(obj.GetType());
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, obj);
return writer.ToString();
}
}
If the argument is a instance of class without parameterless constructor, it will throw a exception.
Unhandled Exception:
System.InvalidOperationException:
CSharpConsole.Foo cannot be serialized
because it does not have a
parameterless constructor. at
System.Xml.Serialization.TypeDesc.CheckSupported()
at
System.Xml.Serialization.TypeScope.GetTypeDesc(Type
type, MemberInfo sourc e, Boolean
directReference, Boolean throwOnError)
at
System.Xml.Serialization.ModelScope.GetTypeModel(Type
type, Boolean direct Reference) at
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type
type , XmlRootAttribute root, String
defaultNamespace) at
System.Xml.Serialization.XmlSerializer..ctor(Type
type, String defaultName space) at
System.Xml.Serialization.XmlSerializer..ctor(Type
type)
Why must there be a parameterless constructor in order to allow xml serialization to succeed?
EDIT: thanks for cfeduke's answer. The parameterless constructor can be private or internal.
During an object's de-serialization, the class responsible for de-serializing an object creates an instance of the serialized class and then proceeds to populate the serialized fields and properties only after acquiring an instance to populate.
You can make your constructor private or internal if you want, just so long as it's parameterless.
This is a limitation of XmlSerializer. Note that BinaryFormatter and DataContractSerializer do not require this - they can create an uninitialized object out of the ether and initialize it during deserialization.
Since you are using xml, you might consider using DataContractSerializer and marking your class with [DataContract]/[DataMember], but note that this changes the schema (for example, there is no equivalent of [XmlAttribute] - everything becomes elements).
Update: if you really want to know, BinaryFormatter et al use FormatterServices.GetUninitializedObject() to create the object without invoking the constructor. Probably dangerous; I don't recommend using it too often ;-p See also the remarks on MSDN:
Because the new instance of the object
is initialized to zero and no
constructors are run, the object might
not represent a state that is regarded
as valid by that object. The current
method should only be used for
deserialization when the user intends
to immediately populate all fields. It
does not create an uninitialized
string, since creating an empty
instance of an immutable type serves
no purpose.
I have my own serialization engine, but I don't intend making it use FormatterServices; I quite like knowing that a constructor (any constructor) has actually executed.
The answer is: for no good reason whatsoever.
Contrary to its name, the XmlSerializer class is used not only for serialization, but also for deserialization. It performs certain checks on your class to make sure that it will work, and some of those checks are only pertinent to deserialization, but it performs them all anyway, because it does not know what you intend to do later on.
The check that your class fails to pass is one of the checks that are only pertinent to deserialization. Here is what happens:
During deserialization, the XmlSerializer class will need to create
instances of your type.
In order to create an instance of a type, a constructor of that type
needs to be invoked.
If you did not declare a constructor, the compiler has already
supplied a default parameterless constructor, but if you did declare
a constructor, then that's the only constructor available.
So, if the constructor that you declared accepts parameters, then the
only way to instantiate your class is by invoking that constructor
which accepts parameters.
However, XmlSerializer is not capable of invoking any constructor
except a parameterless constructor, because it does not know what
parameters to pass to constructors that accept parameters. So, it checks to see if your class has a parameterless constructor, and since it does not, it fails.
So, if the XmlSerializer class had been written in such a way as to only perform the checks pertinent to serialization, then your class would pass, because there is absolutely nothing about serialization that makes it necessary to have a parameterless constructor.
As others have already pointed out, the quick solution to your problem is to simply add a parameterless constructor. Unfortunately, it is also a dirty solution, because it means that you cannot have any readonly members initialized from constructor parameters.
In addition to all this, the XmlSerializer class could have been written in such a way as to allow even deserialization of classes without parameterless constructors. All it would take would be to make use of "The Factory Method Design Pattern" (Wikipedia). From the looks of it, Microsoft decided that this design pattern is far too advanced for DotNet programmers, who apparently should not be unnecessarily confused with such things. So, DotNet programmers should better stick to parameterless constructors, according to Microsoft.
Seems nobody actually read the original post... it is about SERIALIZATION and not DE-... and for this, no constructors are needed or called at all. The issue is simply poor coding practice from Microsoft.
First of all, this what is written in documentation. I think it is one of your class fields, not the main one - and how you want deserialiser to construct it back w/o parameterless construction ?
I think there is a workaround to make constructor private.