I have a problem with a Webservice I'm creating, the thing is, I have a class, name it ClassA with PropertyA, he na ClassB inheriting ClassA that overrides PropertyA using "new" like this:
[DataContract]
public class ClassA
{
[DataMember]
public string PropertyA { get; set; }
[DataMember]
public string PropertyB { get; set; }
}
[DataContract]
public class ClassB : ClassA
{
[DataMember]
public new int PropertyA { get; set; }
}
This should make ClassB "replace" the string PropertyA from ClassA for a int PropertyA in ClassB.
I expose ClassB in a service method like this:
public bool TellMeSomething(ClassB param) { .... whatever .... }
When I add the service reference in the client application, the classes imported show something like this:
public class ClassA
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}
public class ClassB : ClassA
{
public int PropertyA1 { get; set; }
}
As you can notice, ClassB has no "new int PropertyA" anymore, but a "int PropertyA1". I guess the serializer finds the ancestor has a PropertyA already and doesn't know how to handle the "new" keyword to hide the "string PropertyA", so it creates a new name for the PropertyA in the inherited class...
Is there any way to avoid this behavior? I would need that property to be called like it should...
You should use generics instead of identifier re-using:
[DataContract]
public class ClassA<T>
{
[DataMember]
public T PropertyA { get; set; }
[DataMember]
public int PropertyB { get; set; }
}
// No need to override PropertyA since T is int and ClassB
// inherits both PropertyA and PropertyB...
[DataContract]
public class ClassB : ClassA<int>
{
}
Related
I've got a service method which returns a List<BaseClass> but sometimes I might send a DerivedClass : BaseClass in the list.
The issue is I want to send the information through. So far I have:
[DataContract]
public class BaseClass {
string Data { get; set; }
}
and
[DataContract(Name="BaseClass")]
public class DerivedClass : BaseClass {
string MoreData { get; set; }
}
But when the client recieves the data, it's all as a type BaseClass.
You should add KnownType attribute to BaseClass and change Name for DerivedClass or remove it:
[DataContract]
[KnownType(typeof(DerivedClass))]
public class BaseClass
{
string Data { get; set; }
}
[DataContract(Name="DerivedType")]
public class DerivedClass : BaseClass
{
string MoreData { get; set; }
}
KnownTypes
Following should fix your issue:
[DataContract]
[KnownType(typeof(DerivedClass))]
public class BaseClass {
string Data { get; set; }
}
public class DerivedClass : BaseClass
{
}
I have a base class and subclass that are each defined to be serializable using Protobuf-net:
[DataContract]
public class BaseClass
{
[DataMember(Order = 1)]
public string PropertyA { get; set; }
// ...
}
[DataContract]
public class SubClass : BaseClass
{
[DataMember(Order = 101)]
public string PropertyB { get; set; }
// ...
}
Elsewhere:
ProtoBuf.Meta.RuntimeTypeModel.Default[typeof(BaseClass)]
.AddSubType(100, typeof(SubClass));
It has become necessary to move one of the subclass's properties to the base class:
[DataContract]
public class BaseClass
{
[DataMember(Order = 1)]
public string PropertyA { get; set; }
// [DataMember(Order = ?)]
public string PropertyB { get; set; }
// ...
}
[DataContract]
public class SubClass : BaseClass
{
// ...
}
After making this change, is it possible to configure the type model so that PropertyB in BaseClass is serialized at the same position as before to retain compatibility with old clients?
(The ideal solution would use the System.Runtime.Serialization attributes and avoid duplicating the value in the serialized output --as in implementing a new PropertyB in SubClass that uses base.PropertyB to get and set its value.)
I have a class Foo as follows
public class Foo
{
public ClassA A {get;set;}
public string B {get;set;}
}
public class ClassA
{
public string C {get;set;}
}
When I get a Json string (say fooJson), I want to deserialize it to a Foo object with following conditions
The object must have the property Foo.A
Foo.B is optional
Foo.A.C is optional
I tried using MissingMemberHandling = MissingMemberHandling.Error as a part of my JsonSerializerSettings. but that throws error even when Foo.B is missing.
If you want some properties to be optional and some required, the easiest way to achieve this is to mark up your classes with [JsonProperty] attributes indicating which properties are required, e.g.:
public class Foo
{
[JsonProperty(Required = Required.Always)]
public ClassA A { get; set; }
public string B { get; set; }
}
public class ClassA
{
public string C { get; set; }
}
I have a class with 2 interfaces, and I have some superclasses with subclasses, I would like the superclasses to inherit both interfaces. if I just reference the class the interfaces its in, will it work? ie SuperClass : Myinterfaces
here is the class with the interfaces
public class Myinterfaces
{
public interface IBakeable
{
int OvenTemp { get; }
}
public interface IAccounting
{
int Cost { get; }
}
public enum Colors
{
red = 1,
blue,
yellow
}
}
and heres an example of the superclass
public class CeramicsSuperClass : Myinterfaces
{
public string ItemName { get; set; }
public int Cost { get; set; }
public int OvenTemp { get; set; }
}
public class Vases : CeramicsSuperClass
{
private int _BaseDiam;
public Vases(int diam)
{
_BaseDiam = diam;
}
}
You are doing in a wrong way to implement multi-interfaces for a class, try this instead:
public class CeramicsSuperClass : IBakeable, IAccounting {
public string ItemName { get; set; }
public int Cost { get; set; }
public int OvenTemp { get; set; }
}
A class can inherit from only another class but it can implement as many interfaces as possible. When a class inherits from another class and implement some interface, the base class should be listed first, then the interfaces go after like this:
//class A inherits from class B and implements 2 interfaces IC and ID
public class A : B, IC, ID {
//...
}
Simple answer:
You can inherit mulitple interfaces, not multiple classes.
public interface InterfaceA
{
string PropertyA {get;}
}
public interface InterfaceB
{
string PropertyB {get;}
}
public abstract class BaseClassForOthers : InterfaceA, InterfaceB
{
private string PropertyA {get; private set;}
private string PropertyA {get; private set;}
public BaseClassForOthers (string a, string b)
{
PropertyA = a;
PropertyB = b;
}
}
public class SubClass : BaseClassForOthers
{
public SubClass (string a, string b)
: base(a, b)
{
}
}
may be looking here will get you in the general direction (msdn link about interface usage):
http://msdn.microsoft.com/en-us/library/vstudio/ms173156.aspx
How to use DataContract with inheritance? Will code below work?
[DataContract]
public class ConsoleData
{
[DataMember]
public String Description { get; set; }
}
[DataContract]
public class SomeData : ConsoleData
{
[DataMember]
public int Volume { get; set; }
......
Yes, that would work.
The DataContractAttribute has Inherited set to false, so it is necessary to apply the attribute to both the child class and the parent class (as you have done in the question).
You would need to use the KnownType attribute if you want to use your data contracts with polymorphism.
For example
[ServiceContract]
interface MyWcfContract
{
[OperationContract]
HandleData(ConsoleData contractData);
}
If you invoked the method like so:
SomeData someData = new SomeData { Description = "Test", Volume = 30 };
// The method is expecting a ConsoleData instance,
// I'm passing a SomeData instance instead
myWcfProxy.HandleData(someData);
Then the deserializer on the service end will not know that it's an instance of SomeData, just an instance of ConsoleData which it was expecting.
The way to fix this is to register the SomeData class as a known type of the ConsoleData.
[DataContract]
[KnownType(typeof(SomeData))]
public class ConsoleData
{
[DataMember]
public String Description { get; set; }
}
[DataContract]
public class SomeData : ConsoleData
{
[DataMember]
public int Volume { get; set; }
......
You'll need to use the KnownType attribute if you are using the XmlSerializerFormat for your ServiceContract:
[DataContract]
public class ConsoleData
{
[DataMember]
public String Description { get; set; }
}
[DataContract, KnownType(typeof(ConsoleData))]
public class SomeData : ConsoleData
{
[DataMember]
public int Volume { get; set; }
}