Difference in using Attributes/Interfaces in C# - c#

This is not properly a question but something more like a thought I had recently.
I'm taking XmlAttribute to XmlSerialize a class as an example: you can set attributes to a class to choose which properties should be serialized, but the same thing can be done quite easy by implementing a teorical interface IXmlSerializable (it does exist something similar, I don't remember) and by overloading a method "Serialize" for that class which just call Serialize on properties you want to serialize (this.myProp1.Serialize()), same for Deserialize
So what I'm basically saying: isn't Attribute method a bit redundant? (I like it actually, but I don't find it logically different from an interface)
Thanks for any answer, as I've said this is just a thought... hopefully someone will find it interesting
Update 1: Well I explained myself in a wrong way, what I'm asking is "why should I choose attribute instead of an Interface (or opposite)", not exactly this specific case (I took serialization because was the first thing that pop out in my mind), by the way thanks for your answer because they are very interesting

From the comments and downvote, maybe I should highlight my main point here: something that can save me hours of work (per type) and horrible code complexity is very much not redundant, but very, very welcome.
"quite easy"? OK; I'm pretty experienced at serialization, but the implementation for that is not what I call easy. Quite the contrary, in fact.
If you don't want to use attributes, there is an overload for XmlSerializer that allows you to configure it at runtime.
But I shudder whenever I hear "implement IXmlSerializable". The attribute approach is very quick and easy:
[XmlRoot("foo"), XmlType("foo")]
[XmlInclude(typeof(SuperFoo))]
public class Foo {
public string X {get;set;}
[XmlAttribute("y")]
public int? Y {get;set;}
[XmlElement("item")]
public List<string> Items {get;set;}
}
public class SuperFoo : Foo {}
I challenge you to write a robust implementation of IXmlSerializable for that very simple example in under 2 hours... and remember that every line you write is a line you have to maintain.

Well, from the best I can tell, they are logically different.
Implementing IXmlSerializable directly impacts the class itself, because you are adding an interface and one or more methods into the implementation of the class. In essence, You are making your own class directly responsibly for the it's serialization.
However, adding the XmlAttribute attributes does not directly impact the functionality of the class, instead you are just decorating it with attributes so that XmlSerializer can carry out the actual serialization functiohality. In this case, you are deferring the serialization to the XmlSerializer class, and providing just enough metadata about your class for XmlSerializer to do it's work.
This is why I prefer the latter attribute approach. When I'm writing a class, I want it to be serializable, but the last thing I care about is the specifics of the implementation, so I always start with thaqt approach and 99% of the time it works fine with very little work. However, if you did need more fine-grain control over the serialization, the implement the IXmlSerializable interface and write your own serialization code.

The programmatic method of implementing the interface may give a bit more control (and likely more speed), but is harder to create and maintain than the attribute method. I mostly use attributes.

You can select properties to (not) serialize with attributes. Implementation of interface is serialization by code.

Related

Why an interface cannot be serialized? [duplicate]

I would think that adding that attribute to an interface would be helpful make sure you do not create classes that use the interface and forget to make them serializable.
This could be a very fundamental question, but I wanted to ask the experts.
Interfaces define a contract and do not have any state of their own.
Serialization is about saving and loading state into and out of an object model.
Not much point to serializing something that holds no state.
To answer the practical question of forcing an implementation of an interface to be Serializable - this is why the ISerializable interface exists.
In .NET you can declare an interface that should implement other interfaces:
interface MustBeSerializable : ISerializable {}
See some more information here.
If you want to force classes that implement your custom interface IMyInterface to be serializable you can define it has:
interface IMyInterface : ISerializable
{
// Custom interface definition
}
This more clearly indicates that the implementing class should support serialization. This does not remove the need to mark the class with the [Serializable] attribute.
IIRC, you can also create a FxCop custom rule that checks that classes that inherit from IMyInterface are marked with the respective [Serializable] attribute and this way removing the need to classes implement custom serialization.
There are some good albeit esoteric reasons behind what an interface is and isn't which keeps this from being possible. That said however: I agree with you. There are many things that would be useful if we could incorporate them into interfaces. [Serializable] and statics come to mind.
Although they do not fit into the philosophy of what an interface is, they seem to incorporate this vacant grey area in single-inheritance OOP. There are of course work arounds but they feel very forced compared to the original intent.
Well, there is a reason that new classes are not marked as serializable by default: By adding the Serializable attribute, you acknowledge that you have ensured that serialization in your class works, by choosing proper data types for your instance fields and by adding serialization logic, if necessary.
So, if you "forgot" to add the Serializable attribute to your class, you most probably also forgot to check whether serialization really works on your class. Granted, in many cases it will work "out of the box", so adding the attribute is all that remains, but you are supposed to double-check and explicitly acknowledge that fact (by manually adding the attribute).

C# Serialization limitations

i want to implement a general Memento-Pattern in C#. It is working fine but i use the Serializeable() Attribute to do a deep copy of a object. My implementation using generics so if someone use it he has to give his class as type.
Now the class from user must have the Attribute Serializeable() too. Are there any limitations for a class which using Serializeable()?
In fact:
Are there any performance problems?
Is it possible to use an interface?
Is it possible to use inerhitence?
Is it possible to use Auto-Properties?
I dont know how the Attribute works and so iam a bit scary of using this in such a global way.
regards
for small models that you are cloning in memory, not usually
irrelevent; when using [Serializable] you are typically using BinaryFormatter - which looks at the objects themselves; it doesn't matter what interfaces they implement - the interfaces are not used
yes, for the same reason - but all types in the model must be [Serializable]
yes, for the same reason; note : the default BinaryFormatter implementation is looking at fields - it won't even touch the properties
Personally, I try to advise against BinaryFormatter, but this is perhaps not an unreasonable use. However! Be careful that it is easy to suck extra objects into the model accidentally, must commonly through events. Note that it is a good idea to mark all events as non-serialized:
[field:NonSerialized]
public event EventHandler Something;
(or apply to the field directly if using explicit add/remove accessors)
Note also that any members like:
public object Tag {get;set;} // caller-defined
should also probably be [field:NonSerialized].
Personally, I'd prefer a different serializer, but: this will often work. I will say, though: try to avoid persisting the output of BinaryFormatter, as it is hard to guarantee compatibility between revisions of your code.
I dont know how the Attribute works
It does nothing at all except add an IL flag that says "by the way, consider this ok to be serialized"; actually, most serializers don't even look at this flag - but BinaryFormatter is one of the few that do look at this flag. The real code here is BinaryFormatter, which basically does:
have I seen this object before? if so, store the key only
what type is it? is it [Serializable]? store the type info
invent a new reference and store that as the identity
does it have a custom serializer? if so: use that
what fields does it have? access each in turn and store the name/value pair

C#/Salesforce: Must Constrain Generic, Cannot Constrain Generic

This question is equal parts C# and Salesforce, there are probably solutions possible from either side. Suggestions welcome!
I'm writing a generic class to read Salesforce data. The signature looks like this:
public abstract class SalesforceReader<SalesforceObjectType, RecordType>
where SalesforceObjectType: sObject
This lets me use this code later on:
List<RecordType> records = new List<RecordType>();
QueryResult queryResult = service.query(query);
foreach (sObject rawRecord in queryResult.records)
records.Add(ConvertRecord((SalesforceObjectType)rawRecord));
...
public abstract RecordType ConvertRecord(SalesforceObjectType record);
The plan is to write implementations of this class which know how to parse, for example, a Salesforce Lead object into a RecordType, which may be a basic object[], a Dictionary<string, value>, or a fully-defined struct as I choose later on.
So far, I'm all kinds of pleased with my brilliantly elegant solution. My Codey award is as good as won. Then I try to write an implementation. This definition is no good:
class LeadReader: SalesforceReader<Lead, object[]>
The compiler result is:
The type 'SalesforceExtractor.Salesforce.Lead' cannot be used as type
parameter 'SalesforceObjectType' in the generic type or method
'SalesforceUtilities.SalesforceReader<SalesforceObjectType,RecordType>'.
There is no implicit reference conversion from
'SalesforceExtractor.Salesforce.Lead' to
'SalesforceUtilities.Salesforce.sObject'.
Bummer. I have to have the where SalesforceObjectType: sObject constraint in the abstract class so I can cast sObjects, but because the conversion is not implicit, it's not good enough for the implementing class.
Do I need to kiss my neat little solution goodbye, or is there a way to salvage this? This is my first Salesforce project, so if I need to approach things differently, please let me know.
For the bad movie/MST3K buffs out there:
Where do "must" and "cannot" meet on the graph?
Aha, I just needed to walk away for half an hour and look at it again. After 20 years working with computers, you'd think I'd have learned that the problem is usually one of perspective.
Lead does inherit from sObject, but the abstract class was in a library, in a different namespace and project from the implementing class, and each of them was using the Salesforce WSDL. I was asking the compiler to cast SalesforceExtractor.Salesforce.Lead to SalesforceUtilities.Salesforce.sObject, which is not valid. I just had to be more explicit in my implementing class:
class LeadReader: SalesforceReader<SalesforceUtilities.Salesforce.Lead, object[]>
This compiles, and I think I should be good to go.
It sounds like you need to modify the Lead class to inherit from sObject. If those classes are not yours, you need to change your design.
The SF Lead object does inherit from sObject, so this is a job for generic type variance, a subset of covariance/contravariance. Good luck with your Codey acceptance speech.

Why are interfaces not [Serializable]?

I would think that adding that attribute to an interface would be helpful make sure you do not create classes that use the interface and forget to make them serializable.
This could be a very fundamental question, but I wanted to ask the experts.
Interfaces define a contract and do not have any state of their own.
Serialization is about saving and loading state into and out of an object model.
Not much point to serializing something that holds no state.
To answer the practical question of forcing an implementation of an interface to be Serializable - this is why the ISerializable interface exists.
In .NET you can declare an interface that should implement other interfaces:
interface MustBeSerializable : ISerializable {}
See some more information here.
If you want to force classes that implement your custom interface IMyInterface to be serializable you can define it has:
interface IMyInterface : ISerializable
{
// Custom interface definition
}
This more clearly indicates that the implementing class should support serialization. This does not remove the need to mark the class with the [Serializable] attribute.
IIRC, you can also create a FxCop custom rule that checks that classes that inherit from IMyInterface are marked with the respective [Serializable] attribute and this way removing the need to classes implement custom serialization.
There are some good albeit esoteric reasons behind what an interface is and isn't which keeps this from being possible. That said however: I agree with you. There are many things that would be useful if we could incorporate them into interfaces. [Serializable] and statics come to mind.
Although they do not fit into the philosophy of what an interface is, they seem to incorporate this vacant grey area in single-inheritance OOP. There are of course work arounds but they feel very forced compared to the original intent.
Well, there is a reason that new classes are not marked as serializable by default: By adding the Serializable attribute, you acknowledge that you have ensured that serialization in your class works, by choosing proper data types for your instance fields and by adding serialization logic, if necessary.
So, if you "forgot" to add the Serializable attribute to your class, you most probably also forgot to check whether serialization really works on your class. Granted, in many cases it will work "out of the box", so adding the attribute is all that remains, but you are supposed to double-check and explicitly acknowledge that fact (by manually adding the attribute).

Renaming fields then deserializing in C#

I have data stored in an instance of a class which has been serialized with the .net BinaryFormatter. I now want to rename one of the fields in the class, but still be able to deserialize the old data.
One option is to implement ISerializable and deserialize all the the fields of the class manually. But this seems like a lot of work, especially if my class has lots of fields and I've only renamed a single field.
Is there a better way?
Craig suggests keeping a copy of the old class for deserialization, and copying values to the new class. I've seen this suggested elsewhere too - what advantage does this have over implementing ISerializable? As far as I can see, copying the class leaves me with 2 almost identical copies of the class plus I still have to copy all the values from the old class to the new class - which seems the same amount of work as implementing ISerializable with an almost duplicate class thrown into mix.
Two answers have mentioned Binders. I've successfully used a SerializationBinder to deserialize a class Bar which was Serialized as class Foo, but that's because the name of the class changed. Does SerializationBinder also help when you've renamed a field - say when int m_Left has been renamed to int m_Right?
Yes, this is the problem with field-based serializers. You can use either a custom Binder, or a "serialization surrogate" to avoid implementing ISerializable, but that is only a case-by-case fix.
I've discussed this topic (in the context of obfuscators, and auto-props) here. My advice is: don't use BinaryFormatter for persistance of data between versions... for that, look at contract-based serializers:
XmlSerializer
DataContractSerializer
or for binary, things like protobuf-net
None of this helps you today, but it might help you design around it in the future.
You could try having the old calss hang around for the sole purpose of rehydration and then just copy over the fields you need to the new class. Still kind of painful but should work.
I used SerializationBinder class for this before
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx
it can be used for deserialization so you can remap old type to new one.
What if you just change the access modifier on that one property to private, and then have a public property with the new name that just basically wraps the old one. That way you should still be able to deserialize (I THINK) but anyone using this class won't know about the old name. Just a thought...

Categories

Resources