C# serialize JSON Object to a class - c#

I am working on Json Obejct deserielize to a class in .net VS2015 on win 7.
public class1
{
[JsonProperty(TypeNameHandling = TypeNameHandling.Objects)]
public Class1 data1;
public Class2 data2;
}
public abstract Class1
{
some functions
}
public subClass1 : Class1
{
public string myData1 { get; set; }
public string myData2 { get; set; }
}
In my code of deserierlizing:
var mo = MyObject as JObject;
ParentMyClass = mo.ToObject<MyClass>();
I know that an abstract class cannot be instantiated.
So, subClass1 (which is one of the implementation of Class1) is serialized.
But, subClass1 is null after deserialized.
Did I do something wrong ?
UPDATED:
because the code of the classes is too complex, I just simplified the logic.

When you call mo.ToObject<Class1>(); Newtonsoft.Json library will try to create an instance down the line. The problem is you cannot instantiate a abstract. You can see this your self by calling var x = new Class1(); somewhere in you code. This will give you error.
That being said, one thing you could do is create another class that inherits the abstract class.
public class NonAbstract : Class1 {}
this way you will have a class that can be instantiated. And then you can do this.
mo.ToObject<NonAbstract >();

Related

How to copy an instance of base class to derived class base using c#.net

I am encounter with a situation where I need to copy the members of base class to derived class.
I have an Instance of Base class which are returning by some other service, the same class we have used as a base class for further classes.
When we crates an object of derived class I want to assign the already created instance of base class to derived class, I know we can not assign the base class object to derived class but I am still searching any other solution.
Any one has any Idea?
Example :
public class VBase
{
public string Type {get;set;}
public string Colour {get;set;}
}
public class Car : VBase
{
public string Name {get;set;}
public int Year {get;set;}
}
// This class instance I am getting from some other source
VBase mBase= new VBase();
mBase.Type = "SUV";
mBase.Colour = "Black";
//-------------------------------------------------------
Car myCar= new Car();
myCar.Name = "AUDI";
mBase.Year = "2016";
//here I want to copy the instance of base class to derived class some thing like this or any other possible way.
myCar.base=mBase;
It is not possible in naïve way.
I'd like to recommend to define constructor or static method. I personally do not recommend to use additional libraries like AutoMapper for this job as they could require some conversion and make code cumbersome.
public class Car : VBase
{
// Method 1: define constructor.
public class Car(VBase v) {
this.Type = v.Type;
this.Colour = v.Colour;
}
// Method 2: static method.
public static Car FromVBase(VBase v){
return new Car()
{
this.Type = v.Type;
this.Colour = v.Colour;
};
}
public string Name {get;set;}
public int Year {get;set;}
}
Without using reflection, if your classes are lightweight, and wont change overtime, then you could create a public property of Base in Car:
public class Car : VBase
{
public string Name
{
get;
set;
}
public int Year
{
get;
set;
}
public VBase Base
{
set
{
base.Type = value.Type;
base.Colour = value.Colour;
}
}
}
You can then easily pass through your base class like so:
myCar.Base = mBase;
I have created a dotnetfiddle here:
dotnetfiddle for this question

Serialize Abstract class with different attribute name

Working on an export flow, I have a few XML elements that represent the same thing, but with a different name. I can't change those names as they're defined by the other software.
I need something like that:
<class1>
<MY_FIELD></MY_FIELD>
</class1>
<class2>
<my_field></my_field>
</class2>
As the treatments that need to be done on both fields are the same, I wanted to create an abstract class that contains it.
Right now, this is what I have:
public abstract class MyAbstract
{
[XmlAttribute("MY_FIELD")]
public MyField {get;set;}
}
[Serializable]
public class Class1 : MyAbstract
{
}
[Serializable]
public class Class2 : MyAbstract
{
}
Is there a way to specify a different XmlAttribute on the final class (class1 and class2) so I can set the attribute on MyField ?
Edit:
I'm trying to use XmlAttributeOverrides, that seems to do what I want, but I can't make it work. I don't know what I am missing.
var myType = typeof(Class1);
var overrides = new XmlAttributeOverrides();
var attrs = new XmlAttributes
{
XmlAttribute = new XmlAttributeAttribute("test")
};
overrides.Add(myType, "MyField",attrs);
and for the serializer
var serializer = new XmlSerializer(myType, overrides);
Edit2:
Finally I end up removing the attribute on my abstract class and add a getter on each class for serialization purpose. It's crappy but I still hope someone can give me a proper option.
Try
public abstract class MyAbstract
{
abstract public MyField {get;set;}
}
[Serializable]
public class Class1 : MyAbstract
{
[XmlAttribute("MY_FIELD")]
public override MyField {get;set;}
}
[Serializable]
public class Class2 : MyAbstract
{
[XmlAttribute("my_field")]
public override MyField {get;set;}
}

Downcast an inherited class to base class

Let say i have a base class
class baseClass
{ }
And another class that inherit from that baseClass
class foo : baseClass
{ }
I tryed to cast it back directly (baseClass)foo but the compiler say it cannot be done.
Is there a way from foo to get only the baseClass?
foo is a baseClass you don't need any casting. And your code should work without any problems:
var foo = new foo();
baseClass x = (baseClass) foo;
If you derive a class A from class B you can always refer to A as if it were B. Of course this is not true in the revese case. In general you can always refer down the chain of inherited classes.
If the compiler complain on such a thing, it could just mean you have several baseClass defined in several Namespace and you're actually not referencing the right baseClass.
Check your Namespaces it should solve your bug.
Here a working example with different Namespaces
namespace BaseNameSpace
{
public class BaseClass
{
public string Name { get; set; }
}
}
namespace TestNameSpace.Class
{
public class TestClass : BaseClass
{
public string Address { get; set; }
}
}
Use :
TestClass test1 = new TestClass();
BaseClass b = test1;
Ensure that there is the correct using :
using BaseNameSpace;
using TestNameSpace.Class;

c# get field (property) values of derived class in base constructor

I have 2 classes:
public class Class1
{
private string Name1;
public Class1()
{
//How to get Name2 of the derived class?
}
}
public class Class2 : Class1
{
private string Name2 = "asd";
public Class2(){}
}
How to get Name2 of the derived class in the base constructor?
public class Class1
{
private string Name1;
public Class1()
{
class2 xxx = this as class2
if (class2 != null)
this.Name1 = xxx.Name2;
}
}
"this as class2" - is not null
This example is correct. The only thing is I don't know Derived class is Class2 or class3 or class4 .... I need universal code
You cannot (and more importantly, you should not) do that. When you are in the constructor of the base class, the subclass portion has not been initialized yet, so there is no way to get to the members of the subclass: quite simply, they do not exist yet.
Another problem is that the Name2 attribute may not be present in a subclass at all, even at the level fo the definition: I can derive Class3 from Class1, and give it Name3 attribute instead of Name2.
All this does not touch on such "insignificant" matters as breaking encapsulation: Name2 is a private member, which may be removed in the future implementations of the Class2.
The only way for the subclass to communicate things to superclass in a constructor is passing parameters. This would work:
public class Class1 {
private string Name1;
public Class1(string subclassName2)
{
// Subclass has passed its Name2 here
}
}
public class Class2: class1 {
private string Name2;
public Class2(string myName) : base(myName) {
Name2 = myName;
}
}
You can access the code in the derived class from the base class code, but only from within an object which is actually a derived class object, and then only if the methods involved are virtual methods.
If you have an object which is itself an instance of the base class, then from within that instance you cannot see derived class code from the base class .
example
public class Baseclass{
public void Foo()
{
Bar();
}
public virtual void Bar()
{
print("I'm a BaseClass");}}
public classs Derived: BaseClass{
public override void Bar()
{
print("I'm a Derived Class");}}
Main()
var b = new BaseClass();
x.Foo() // prints "I'm a BaseClass"
// This Foo() calls Bar() in base class
var d = new Derived();
d.Foo() // prints "I'm a Derived Class"
// in above, the code for Foo() (in BaseClass)
// is accessing Bar() in derived class
I think you could not because when you instantiate derived class, base class constructor is called first to initialize base class and then the derived class is initialized.Within the base class constructor there is no way to access derived class members because they are not available at that time.
You cannot do it. It strictly violates the Object Oriented Approach programming ground rules.
As each instance of Class2 will have the Name2 property. But the same cannot be guaranteed for instance of object for Class1.
It's not really clear what you're trying to achieve. It is possible to do the following, but I don't think it's good practice:
interface IHasName2
{
string Name2 { get; }
}
class Class1
{
string Name1;
public Class1()
{
var withName2 = this as IHasName2;
if (withName2 != null)
{
Name1 = withName2.Name2;
}
}
}
Then classes deriving from Class1 may implement IHasName2 if they like.
But maybe you want an abstract class to make sure derived classes specify a Name2. It could be like this:
abstract class Class1
{
string Name1;
// instance property required to be implemented by deriving classes
protected abstract string Name2 { get; }
// instance constructor
protected Class1()
{
// 'Name2' can be read already here (dangerous?)
Name1 = Name2;
}
}
Finally, consider the simple solution proposed by dasblinkenlight to have the instance constructors of Class1 take in a string parameter for the name. Deriving classes would then have to supply that name parameter when they "chain" their base class constructor.

Dynamically add a Property to a System.object?

I got a list of different objects that I defined in different classes and I'd like to add a string property "Name" to all these objects. Is that possible ?
I don't have that much code to provide as my classes are very simple/classic ones.
Thanks in advance for any help !
(edit : I don't want to inherit from an abstract class that adds this property ! In fact, I don't want to modify at all my class that define my object. That's what i call "Dynamically" in the title.
What I want is something like :
myObject.AddProperty(string, "Name");
or
myObject.AddAttribute(string, "Name");
(I don't know how it is exactly called)
and then I can do :
myObject.Name = "blaaa";
Create an abstract class that all of your other classes could inherit:
public abstract class MyBaseClass
{
public string MyCommonString { get; set; }
}
public class Foo : MyBaseClass
{
public MyBaseClass() { }
}
//Create instance of foo
Foo myFoo = new Foo();
//MyCommonString is accessible since you inherited from base
string commonString = myFoo.MyCommonString;
EDIT (per new requirement)
Since you don't want to touch the original classes in the DLL, I'd take this [similar] approach:
public abstract class MyBaseClass
{
public string MyCommonString { get; set; }
}
//This class definition lives in the DLL and remains untouched
public class Foo
{
public Foo() { }
}
//This partial class definition lives in [insert new project name here]
public partial class Foo : MyBaseClass
{
public Foo () { }
}
Notice that Foo is now a partial class. You're not touching the existing class definition in the DLL, you're extending it.
EDIT (per newer new requirement)
Given your requirements (no editing of original class), what you're asking is not possible.
What you can do is to hard code a Hashtable named CustomProperties
Now you can fill this Hashtable with custom properties
Something like that:
MyClass myClass = new MyClass();
myClass.SetProperty("abc", 123);
myClass.SetProperty("bcd", "bla");
myClass.SetProperty("cde", DateTime.Now);
MessageBox.Show(myClass.GetProperty("abc").ToString());
class MyClass
{
private Hashtable MyProperties { get; set; }
public MyClass()
{
MyProperties = new Hashtable();
}
public object GetProperty(string name)
{
return MyProperties.Contains(name) ? MyProperties[name] : null;
}
public void SetProperty(string name, object value)
{
if (MyProperties.Contains(name))
MyProperties[name] = value;
else
MyProperties.Add(name, value);
}
}
You want to use the new C# 4.0 dynamic keyword:
dynamic obj = new System.Dynamic.ExpandoObject();
obj.Value = 10;
var action = new Action<string>((l) => Console.WriteLine(l));
obj.WriteNow = action;
obj.WriteNow(obj.Value.ToString());
You can not do this with object, but the ExpandoObject will do just fine.
But... overuse dynamic typing and you'll find yourself in a maintenance nightmare in the near future.

Categories

Resources