I am working on a ASP.NET application that has a class that inherits a List of a Custom Object.
public class UserRoleList : List<UserRoleBO> {
public UserRoleList() { }
}
How do I make this class serializable in C#?
I believe you really just need to ensure that UserRoleBO is serializable and the list will take care of itself. This assumes the values you want to serialize are public properties on the UserRoleBO and UserList. For more info see What is the point of the ISerializable interface?
You need to do the following
Ensure UserRoleList is serializable
Ensure UserRoleBO is serializable
Ensure the type of all fields inside UserRoleBO are serializable (this is recursive)
The easiest way to do this is to add the [Serializable] attribute to the classes. This will work in most cases.
On a different note, deriving from List<T> is usually speaking a bad idea. The class is not meant to be derived from and any attempt to specialize it's behavior can be thwarted in sceanarios where the derived class is used from a List<T> reference. Can you explain why you want to derive in this way? There is likely a more robust solution.
Like so:
[Serializable]
public class UserRoleList : List<UserRoleBO> {
public UserRoleList() { }
}
(Note the 'Serializble' tag will need to be on all classes that need to be serialised (so the parent as well.
And then use BinarySerialization to do it.
Related
I am trying to learn a smart, design pattern-ish way of validating the properties of a library class that holds the data of an e-commerce order returned from a web-service (eBay SDK).
There are other questions on this, but I haven't been able to apply them to my situation because:
The class I want to validate is from an SDK, it does not have properties marked virtual, deriving from it means I have to hide the base properties with new and call base in the new properties to access them.
If I derive from the base class and use the new modifier with base.propertyName, to effectively duplicate the class properties and also be able to add the validation attributes above them, I cannot cast the object I'm trying to validate to this derived class with attributes to be able to call .Validate() as you cannot 'cast up' from a base-type to a derived type.
Is there any approach to contract-style class properties validation, whereby you have no class-definition control of the class you're validating? Instead of creating a validator class that has 20 if-statements doing null-checking and logic on each property?
I only need this for a specific object and I know the properties and what values are valid, I just don't feel passing the order to a class with a bunch of if-statements is good in terms of maintainability and code-quality.
Here is the code I was thinking of for the derived type I could invoke .Validate() on, I stopped writing this as I don't know how to take baseclass, transform it into this class:
public class ValidatableOrderType : eBay.Service.Core.Soap.OrderType
{
public ValidatableOrderType(eBay.Service.Core.Soap.OrderType baseType)
{
}
[Required(ErrorMessage = "OrderID cannot be null.")]
new public string OrderID
{
get { return base.OrderID; }
}
}
I think your best choice its to use fluentvalidator.
https://fluentvalidation.net/
Its a brilliant software for validation even more powerful than metadata attributes.
I hope this helps you
I was trying to create an attribute that implies [Serializable] but I noticed that this SerializableAttribute class is sealed.
In Java it was possible to create an interface (say, MyInterface) that is inherited from Serializable interface and so all the subclasses of MyInterface would also be serializable, even its sub-sub classes would be so.
Let's say I am creating an ORM and I want customers to annotate their entity classes as [DatabaseEntity] but in order to make sure that entities are serializable, I also need to ask them to attribute their classes with extra [Serializable] which does not look quite compact and neat.
I am wondering why SerializableAttribute class is sealed and why has Inherited=false which implies that subclasses of serializable class will not be serializable unless it is explicitly stated. What motives are behind these design choices?
The SerializableAttribute is only used by the BinaryFormatter. If you are writing your own serialiser then don't worry about.
The sealed keyword is applied to the attribute not the class associated with the attribute. It is saying that the SerializableAttribute cannot be subclassed.
The BinaryFormatter uses an opt-in model. Any class (or subclass) must specify that it is serializable. This why the Inherited=false is used.
It's suggested best practice that all .Net attributes should be sealed, according to Microsoft:
The .NET Framework class library provides methods for retrieving custom attributes. By default, these methods search the attribute inheritance hierarchy; for example System.Attribute.GetCustomAttribute searches for the specified attribute type, or any attribute type that extends the specified attribute type. Sealing the attribute eliminates the search through the inheritance hierarchy, and can improve performance. [my emphasis]
So [Serializable] is sealed because it's quicker for .Net reflection to check the attributes. The cost is that you can't inherit and extend SerializableAttribute.
You can make your own un-sealed attributes if you want (you'll get code analysis warnings though).
This gets a little confusing with how attributes are used in inheritance for the classes that they apply to. It's probably best to use an example:
[Serializable]
public class A
{
public int SimpleSerialisableProperty { get; set;}
}
public class B : A
{
public C ComplexReferenceProperty { get; set; }
}
[Serializable]
public class D : A
{
public bool AnotherSerialisableProperty { get; set;}
}
You asked why SerializableAttribute.Inherited = false and this is why:
Class A is marked as [Serializable], and it is.
However class B inherits A and extends it with properties that are not serialisable. If .Net tries to serialise B it will encounter an error.
That Inherited = false tells .Net that just because A has been marked as [Serializable] not every class that inherits it will be serialisable too.
Now class D inherits A and is serialisable, so it gets its own [Serializable] attribute.
Finally, in terms of design attributes are a great way of extending behaviour (nice UI editors in property grids, etc). However they are terrible at enforcing it. If you need your customers to implement their entity classes in a particular way then an abstract base class or an interface is a much better way to go. If you make it an attribute then you're basically letting them know that [Serializable] is an option that you can handle either way.
Serialization is not a magic thing and you don't need any attribute to serialize an object. It is a process of writing your class' properties and fields to a stream (and attributes are only directives to serializers about how to behave while outputting an object).
See this over-simplified serializer code which totally ignores all attributes including NonSerializable
object obj = yourObject;
var props = obj.GetType()
.GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(obj, null));
string serializedText = String.Join("\n",
props.Select(kv => kv.Key + "=" + kv.Value ?? kv.Value.ToString()));
Above code, for example, would give
IsEmpty=False
X=3
Y=5
for object obj = new Point(3,5);
Deserialization process would be to read these values and set the properties back accordingly.
Put the [Serializable] attribute on top of the class you want serialized. Serialization is opt-in process. You have to manually do that for each class you want serialized. There are bunch of other keywords.
In a namespace, is it possible to provide an alias for a class? And if not, why not?
By example, if I had several libraries of things that were derived from a contained, but named base class, but wanted to alias that as "BaseClass", while retaining its actual class name (i.e. "HtmlControl").
Then consumers could always come along and extend from HtmlControls.BaseClass, without having to figure out which class it really comes from.
using SomeClass = Large.Namespace.Other.FunkyClass;
class Foo : SomeClass
{
}
There really isn't an ideal way to do this in C#/.NET. What you can do is have a public BaseClass that inherits from an internal class. You can change this inheritance internally without breaking your consumers as long as the interface to the class remains intact.
public class PublicBaseClass : SomeInternalClass {
}
Consumers inherit from PublicBaseClass, and as long as you are careful, you can change what SomeInternalClass is as you wish.
You could create a dummy class that just inherits HtmlControl without adding any other functionality:
public class BaseClass : HtmlControl {}
The closest I know of is to customize your using statement:
using BaseClass = HtmlControls.BaseClass;
This is normally used to avoid ambiguity between classes with the same name in different used namespaces, without having to fully qualify one or the other. Your devs would have to include it in every code file, so probably not a good solution for what you're doing.
As far as deriving from BaseClass without knowing what you are actually deriving from, not possible. The compiler must, at some level, know what and where the parent class is, meaning it must be statically defined somewhere in code.
I've got a C# structure of classes with an abstract base class and various classes derived from this abstract class.
[System.Xml.Serialization.XmlInclude(typeof(B))]
public abstract class A {
...
}
[Serializable]
[XmlType("typename")]
public class B : A {
...
}
Furthermore, I'm using an instance of class B within another class C as a field with its abstract type like this:
public class C {
...
public A myItem { get; set; } //A is actually of type B
...
}
Now, when I serialize my class C via the standard xmlserializer, I get a XML structure like this:
<C>
<myItem p2:type="typename" xmlns:p2="...">
... //Fields as elements and stuff
</myItem>
</C>
But thats not what I need because I send those serialized C objects to a REST Webservice (which has no valid schema yet). What I actually need is something like this:
<C>
<typename>
... //Fields as elements and stuff
</typename>
</C>
But as you can see above, the xmlserializer seems to prefer the instance field name over the type name set via XmlType. Also, obviously I can't just use XmlElement("typename") for my field in C, because I don't know which concrete implementation of my abstract class A the field will contain.
Has anyone ever had a similar problem and could provide me with a solution to this? Or do i really need to implement IXmlSerializable in my class A and thus within all of my concrete A-derived classes to get this working?
EDIT: Just found out while reading some articles that IXmlSerializable doesn't let me control the wrapper element, so do I actually need to implement the Interface in class C with some sort of switch() on the type of the myItem member?
Thanks for your help!
Best regards,
flo
Okay, seems I have found the solution, at least for serialization, don't know yet if this also works for deserialization. The key is a special constructor for the XMLElement attribute, which allows to specify the key to use if a abstract type is used:
http://msdn.microsoft.com/en-us/library/cz6bdh5z.aspx
Maybe this is also helpful to someone else.
Best,
flo
For deserialization you will need to provide the XmlSerializer with all the types that it MAY encounter in all the abstract typed properties.
The XmlSerializer has a specific constructor in which you can feed it a collection of Types.
I have a whole list of entity classes which I need to make Serializable (due to storing session state in SQL, but that's another story).
I have added the attribute [Serializable] and all seems to be fine.
All of my entity classes extend from the same base class.
If I mark the base class as Serializable, does this mean all children are marked as Serializable too?
Thanks
No, attribute is not inherited.
When you extend the class, it's possible to add features that might not be serializable by nature therefore .NET framework cannot assume for you that everything what extends serializable base class is also serializable.
That's why you must explicitly state [Serializable] attribute on every class individually.
Nope, each one will have to be marked as [Serializable] specifically.
Also if you intend to serialize an object to XML which is of a derived type as though it is the base type you'll also need a [XmlInclude] attribute.
EG:
[Serializable]
public class BaseClass : ParentClass
{
}
[Serializable]
[XmlInclude(typeof(BaseClass))]
public class ParentClass
{
}
(Binary serialization, like what is used for sessions, do not need this)