DataContract inherit from a non-DataContract base class - c#

Is it possible (and if so then how) to inherit from a base class that doesn't implement [DataContract] and tell the serializer to ignore it?
So something like
//Non-accessible, non-[DataContract] class
public class ThirdPartyOrFrameworkClass
{
public void ConvenienceMethod()
{
//Code
}
//Rest of the class
}
[DataContract (IgnoreBaseClassWhenSerializing = true)]
public class SomeStateClass : ThirdPartyOrFrameworkClass
{
[DataMember]
string _data;
//Rest of the class
}
If not, what's the solution to using a class that doesn't implement the [DataContract] attribute?
I'd prefer to use the DataContractSerializer than the XmlSerializer?

I think the answer to your question in NO (if you can't change the ThirdPartyOrFrameworkClass source code).

Related

ProtoBuf is not serializing a field in inherited class [duplicate]

This question already has answers here:
How to Serialize Inherited Class with ProtoBuf-Net
(2 answers)
Closed 6 years ago.
I have a base class called PrivilegeType and it's inherited by various other classes.
Everything works fine except for one specific field called PossibleValues which doesn't get serialized/deserialized well.
Base class definition:
[ProtoContract]
[ProtoInclude(13, typeof(PrivilegeEnum))]
public abstract class PrivilegeType {
...
}
PrivilegeEnum definition:
[ProtoContract]
public class PrivilegeEnum : PrivilegeEnumLike<PrivilegeEnumValue> {
...
}
PrivilegeEnumLike<T> definition:
[ProtoContract]
public abstract class PrivilegeEnumLike<T> : PrivilegeType<T>
{
[ProtoMember(2)]
public Dictionary<string, PrivilegeEnumValue> PossibleValues;
...
}
PrivilegeEnumValue definition:
[ProtoContract]
public class PrivilegeEnumValue
{
[ProtoMember(1)]
public string Value;
[ProtoMember(2)]
public string Text;
[ProtoMember(3)]
public HashSet<PrivilegeEnumValue> ImpliedValues = new HashSet<PrivilegeEnumValue>();
...
}
The thing is, that field is defined inPrivilegeEnumLike<T> which is not included in ProtoInclude list itself, but its subclasses are. I can't add PrivilegeEnumLike<> to ProtoInclude list because I guess it doesn't make sense.
Here's the rule:
Class hierarchy must be implemented correctly.
This means you need to use ProtoInclude on parent classes, NOT necessarily base classes
Otherwise, any inherited class between your subclass and baseclass will not get serialized.
What I did:
Base class:
[ProtoContract]
[ProtoInclude(12, typeof(PrivilegeEnumLike<PrivilegeEnumValue>))]
[ProtoInclude(13, typeof(PrivilegeEnumLike<PrivilegeEnumValue[]>))]
public abstract class PrivilegeType
Middle class:
[ProtoContract]
[ProtoInclude(20, typeof(PrivilegeEnum))]
[ProtoInclude(21, typeof(PrivilegeEnumSet))]
public abstract class PrivilegeEnumLike<T> : PrivilegeType<T>
Everything works correctly now.
Please let me know if there's any better solution to this.

Serialize delivered class's instance using DataContract

I have library with class in it looks like next:
[DataContract]
class MyBaseClass
{
public string Name { get; set; }
}
Also, I have another project with ref of this library and class in it looks like:
[DataContract]
class MyDeliveredClass : MyBaseClass
{
public string SecondName { get; set; }
}
I wonder how could I serialize list<MyBaseClass> which could contain objects of MyBaseClassand MyDeliveredClass ?
May be I should use [KnownType(MyDeliveredClass)]... but I have no reference to MyDeliveredClass in library...
If you declare both MyBaseClass and MyDeliveredClass as Service known types on the service contract interface then that should do the trick:
[ServiceContract(SessionMode = SessionMode.Required, ...)]
[ServiceKnownType(typeof(MyBaseClass ))]
[ServiceKnownType(typeof(MyDeliveredClass ))]
public interface IMySerivceContract {
...
}
Generally you have to choice between delclaring as KnownTypes on the class declaration or as ServerKnownTypes on the service interface. However sometimes the KnownType route is not an option for various reasons - one of which is your situation where you dont have access to a class declaration. Another case where you are forced to use ServiceKnownTypes is if your contract uses interfaces instead of the base class i.e if your contract had List<IMyBaseInterface>.

XML serialization of a member using an abstract class using generics

I am having trouble with XML serialization for members that use generics. The following is what my basic class structure looks like (and I want to use the default XML serialization, not overload IXmlSerializable in every class):
public class MyClassToSerialize
{
public Problem<int> Problem;
}
public class MyOtherClassToSerialize
{
public Problem<string> Problem;
}
public abstract class Problem<T>
{
}
public class ProblemImplementationOne<T> : Problem<T>
{
}
public class ProblemImplementationTwo<T> : Problem<T>
{
}
Now here is what I tried:
[XmlInclude(typeof(ProblemImplementationOne<T>))]
[XmlInclude(typeof(ProblemImplementationTwo<T>))]
public abstract class Problem<T>
{
}
This doesn't work: it gives a compile error on the <T> parameter used in the attributes. The following (obviously) doesn't work as well, because it doesn't give enough information for serializing:
[XmlInclude(typeof(ProblemImplementationOne<>))]
[XmlInclude(typeof(ProblemImplementationTwo<>))]
public abstract class Problem<T>
{
}
This gives the error at serializing: "Generic type definition cannot be used in serialization. Only specific generic types can be used."
Does anyone know an easy solution to this problem?
Something like this, depending on the actual runtime type of the Problem properties in the objects you're serializing:
[XmlInclude(typeof(ProblemImplementationOne<int>))]
[XmlInclude(typeof(ProblemImplementationTwo<int>))]
public class MyClassToSerialize
{
public Problem<int> Problem;
}
[XmlInclude(typeof(ProblemImplementationOne<string>))]
[XmlInclude(typeof(ProblemImplementationTwo<string>))]
public class MyOtherClassToSerialize
{
public Problem<string> Problem;
}

subclassing and data contracts

I'm playing with the following code:
[ServiceContract]
public interface IUserAccountService
{
[OperationContract]
UserAccountResponse CreateNewUserAccount(UserAccountRequest userAccountRequest);
}
public abstract class BaseResponse
{
public bool Success { get; set; }
public string Message { get; set; }
}
public class UserAccountResponse : BaseResponse
{
public int NewUserId { get; set; }
}
My questions are:
Do I need to add the DataContract attribute to both the abstract class and the subclass?
If the abstract class does not need the DataContract attribute, can I add the DataMember attribure to its properties?
If you want items in the base class to be serialized, then you must apply DataContract to the base class and apply DataMember to those items that are to be serialized in the base class. However, if you do not want anything in the base class to be serialized, then you shouldn't need to specify DataContract on the base class.
From the MSDN documentation:
"When you apply the DataContractAttribute to a base class, the derived types do not inherit the attribute or the behavior. However, if a derived type has a data contract, the data members of the base class are serialized. However, you must apply the DataMemberAttribute to new members in a derived class to make them serializable."
Yes you will have to use [DataContract] on both BaseResponse and UserAccountResponse. You will also have to use the [KnownType] attribute for every subclass as shown below.
[KnownType(typeof(UserAccountResponse))]
[DataContract]
public abstract class BaseResponse
{
...
}

Problem with XML serialisation and C#

I am trying to serialise some C# classes to XML. Things were going fine until I tried to introduce some inherited classes.
The classes are [edited for size]
public class ParticipationClass
{
[XmlAttribute]
public string typeCode;
[XmlAttribute]
public string contextControlCode;
public ParticipationClass()
{
}
}
public class p_recordTarget : ParticipationClass
{
public p_recordTarget()
{
typeCode = "RCT";
contextControlCode = "OP";
}
}
when using the classes the following code is used :
public class Test
{
// other class attributes excluded..
[XmlElement]
public ParticipationClass recordTarget;
private void Test()
{
recordTarget = new p_recordTarget();
}
}
The serialisation fails with an InvalidOperationException, looking in the exception detail I can see "Message="The type itk.cda.cdaclasses.p_recordTarget was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."
So I guess I need an XmlInclude, but I am not sure how.
In a nutshell, you need to use the attribute on the base class to let the serializer know about the derived classes:
[XmlInclude(typeof(p_recordTarget))]
public class ParticipationClass {
// ...
}
This may help you out:
http://www.codeproject.com/KB/XML/xmlserializerforunknown.aspx
Like this:
[XmlInclude(typeof(p_recordTarget))]
public class ParticipationClass
{
[XmlAttribute]
public string typeCode;
[XmlAttribute]
public string contextControlCode;
public ParticipationClass()
{
}
}

Categories

Resources