C# serialization dropping property in subclass? - c#

When I try to serialize a populated instance of type List<C>() where:
public class A<T> : List<T>
{
[XmlAttribute("Name")]
public string Name {get; set;}
public A() {}
}
public class B
{
[XmlAttribute("Other")]
public string OtherPCO { get; set:}
}
public class C : A<B>
{
}
The serialization drops the Name property of class A but does create an array of type B with the OtherPCO property. How can I get the serializer to include Name?

Collections are serialized in a specific manner, which takes into account only the items of the collection, not the extra properties you added to the class. You need to wrap the collection in another class that is not a collection.
This should give you the desired result :
public class A<T>
{
[XmlAttribute("Name")]
public string Name {get; set;}
[XmlElement(typeof(T))]
public List<T> Items { get; set; }
}

Related

Access hidden property in base class c#

In my ASP.NET Core API, I have a DTO class BaseDto and another DerivedDto that inherits from BaseDto and hides some of its properties, because they're required in DerivedDto. I also have a BaseModel class to which both BaseDto and DerivedDto will be mapped through another class Mapper.
Something like the following code:
using System.ComponentModel.DataAnnotations;
public class BaseDto
{
public string Name { get; set; }
}
public class DerivedDto : BaseDto
{
[Required]
public new string Name { get; set; }
}
public class BaseModel
{
public string NameModel { get; set; }
}
public static class Mapper
{
public static BaseModel MapToModel(BaseDto dto) => new BaseModel
{
NameModel = dto.Name
};
}
But it turns out, when passing a DerivedDto object to the MapToModel method, it's trying to access the values of the BaseDto (which are null) instead of the DerivedDto ones.
Is there any way I can achieve this behavior?
I can only think of declaring BaseDto as abstract, but that would prevent me from instantiating it, which I need to do.
You need to declare your BaseDto class property as virtual and then override it in the DerivedDto class as follows:
public class BaseDto
{
public virtual string Name { get; set; }
}
public class DerivedDto : BaseDto
{
public override string Name { get; set; }
}
Also, please fix your Mapper class method. There is no property Name in the BaseModel. It needs to be "NameModel = dto.Name"

Deserialize property from JSON twice?

I have a weird problem:
I have a class A which contains a subclass B. class A is rather complex and changes frequently. I do need only a small fraction of the properties of class A and a complete json representation of class B, to pass it on to a different service.
This looks like this
[DataContact]
public class A
{
[DataMember]
public B Inner {get; set;}
}
[DataContact]
public class B
{
[DataMember]
public int SomeThing {get; set;}
}
What I would like to achieve is this:
[DataContact]
public class ADesired
{
[DataMember]
public B Inner {get; set;}
[DataMember]
public string InnerAsJsonString {get; set;}
}
I tried the most obvious ideas (e.g. a Jsonproperty which refers to the same name, but NewtonSoft.Json refusses to make this work)
What I have tried so far:
JsonConverter, did not work at all.
JsonProperties:
[DataContact]
public class ADesired
{
[JsonProperty("Source")]
public B Inner {get; set;}
[JsonProperty("Source")]
public string InnerAsJsonString {get; set;}
}
Which does not work at runtime, since the reference to the same property is detected.
Nuclear option: Just deserialize the string twice in the controller, but this feels just wrong.
One option is to serialize it in the class
[DataContact]
public class ADesired
{
[DataMember]
public B Inner {get; set;}
public string InnerAsJsonString => Newtonsoft.Json.JsonConvert.SerializeObject(Inner);
}
If you don't care about performance, you could use JObject as the Json-Property type.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
[DatanContract]
public class ADesired
{
[JsonIgnore]
public B Inner { get; set; }
[JsonIgnore]
public string InnerJson { get; set; }
[DataMember]
[JsonProperty(nameof(Inner))
public JObject JInner
{
get => JObject.FromObject(Inner);
set { Inner = value.ToObject<B>(); InnerJson = value.ToString(); }
}
}
That way when deserializing, the actual json is saved as InnerJson and what can be, is deserialized into Inner, and when serializing back, whatever is in Inner will get serialized.

C# Implement derived Types of an Interface Definition?

I have an inheritance tree, which looks like this:
Foo and Bar both have an Id, as defined through an specific Id class.
The id classes itself are derived from a common base class.
I would now like to write an interface which can encompass both Foo and Bar,
but the compiler does not allow that, I would have to use BaseId as the type in Foo and Bar, but I would like to avoid that.
public class BaseId
{
public string Id {get; set;}
}
public class FooId: BaseId
{}
public class BarId: BaseId
{}
public interface MyInterface
{
public BaseId Id {get; set; }
}
public class Foo: MyInterface
{
public FooId Id {get; set;}
}
public class Bar: MyInterface
{
public BarId Id {get; set;}
}
Generics can help here. First you define interface like this:
public interface IMyInterface<out T> where T : BaseId {
T Id { get; }
}
And then you can implement it like this:
public class Foo : IMyInterface<FooId> {
public FooId Id { get; set; }
}
public class Bar : IMyInterface<BarId> {
public BarId Id { get; set; }
}
Achieving your goal to use BarId and FooId in specific classes.
Both classes are also castable to IMyInterface<BaseId> in case you are in situation where you don't know the exact id type:
Foo foo = new Foo();
// works fine
var asId = (IMyInterface<BaseId>)foo;

Required base class for property

I have a class that has a property, and I want to force that this property is of a Type that inherits from a base type
public abstract class BasePropertyClass
{
public string A { get; set;}
}
public class MyPropClass : BasePropertyClass
{
public string B { get; set;}
}
public class MyOtherPropClass : BasePropertyClass
{
public string C { get; set;}
}
public class MyClass
{
public MyPropClass MyPropThatMustInheritBasePropertyClass { get; set;}
}
public class MyOtherClass
{
public MyOtherPropClass MyPropThatMustInheritBasePropertyClass { get; set;}
}
So, how can I make an Interface-ish solution that MyClass and MyOtherClass must have a property MyPropThatMustInheritBasePropertyClass that must have BasePropertyClass as base type
You can make your class generic and add a constraint
public class MyClass<T> where T : BasePropertyClass
{
public T MyPropThatMustInheritBasePropertyClass { get; set;}
}
To better explain #Selman22 answer, you can do something like this:
public abstract class ConstrainedClass<T>
where T: BasePropertyClass
{
public T MyPropThatMustInheritBasePropertyClass { get; set;}
}
In this way, if you declare the other to classes like this:
public class MyClass:ConstrainedClass<MyPropClass>
{
}
public class MyOtherClass:ConstrainedClass<MyOtherPropClass>
{
}
you will obtain the same classes as you declared in your question, plus you have the constraint in the property.
If your classes already inerhits from another class, you need an additional step:
public interface ConstrainedInterface<T>
where T: BasePropertyClass
{
T MyPropThatMustInheritBasePropertyClass { get; set;}
}
and after you must explicitly define the two properties:
public class MyClass : ConstrainedInterface<MyPropClass>
{
public MyPropClass MyPropThatMustInheritBasePropertyClass { get; set;}
}
and
public class MyOtherClass : ConstrainedInterface<MyOtherPropClass>
{
public MyOtherPropClass MyPropThatMustInheritBasePropertyClass { get; set;}
}
You could just use your base type:
public class MyClass
{
public BasePropertyClass Property1 { get; set;}
}
public class MyOtherClass
{
public BasePropertyClass Property2 { get; set;}
}
since both MyPropClass and MyOtherPropClass inherits the same base type, BasePropertyClass.
This way you could assign to either Property1 or Property2 and object of type MyPropClass or MyOtherPropClass.
You can't directly, because the implemented property must be exactly of the type specified in the interface.
Alternative to #Selman's generic solution, you can do so using a backing field:
public interface MyClassInterface
{
BasePropertyClass MyPropThatMustInheritBasePropertyClass { get; set;}
}
public class MyClass : MyClassInterface
{
private MyPropClass _actualProperty;
public BasePropertyClass MyPropThatMustInheritBasePropertyClass
{
get { return _actualProperty; }
set { _actualProperty = (MyPropClass)value; }
}
}
This assumes the not specified requirement "I want to have a member of the derived type in the implementing class", which MyPropClass _actualProperty fulfills.
This will not ensure type safety for the setter, which may throw a cast exception when setting a variable of the wrong type (in this case MyOtherPropClass).

Set requried field while Deserializing using Json.Net

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; }
}

Categories

Resources