Deserializing "old" xml into new class instance - c#

I've had a class which looked like
public class MyClass
{
public string EmployerName;
public string EmployerSurname;
public string EmploeeName;
public string EmploeeSurname;
}
I've refactored the code above to this:
public class MyClass
{
public MyClass()
{
Employer = new PersonInfo();
Emploee = new PersonInfo();
}
public class PersonInfo
{
public string Name;
public string Surname;
}
public PersonInfo Emploee;
public PersonInfo Employer;
[Obsolete]
public string EmploeeName
{
get
{
return Emploee.Name;
}
set
{
Emploee.Name = value;
}
}
[Obsolete]
public string EmploeeSurname
{
get
{
return Emploee.Surname;
}
set
{
Emploee.Surname= value;
}
}
[Obsolete]
public string EmployerName
{
get
{
return Employer.Name;
}
set
{
Employer.Name = value;
}
}
[Obsolete]
public string EmployerSurname
{
get
{
return Employer.Surname;
}
set
{
Employer.Surname = value;
}
}
Problem is, that when deserializing XMLs, which were serialized from old class version, I hoped that the new properties would work, and fields of the inner objects would be filled, but they don't.
Any ideas how, besides implementing IXmlSerializable, I could modify the new class to support both new and old versions of XMLs? Or maybe IXmlSerializable is the only way?

Do you only want to support the old ones for deserialization? if so, you could have:
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public string EmploeeName {
get { return Emploee.Name; }
set { Emploee.Name = value; }
}
public bool ShouldSerializeEmploeeName() { return false;}
The bool method tells XmlSerializer never to write this, but it will still be read. [Browsable] tells it not to appear in things like DataGridView, and [EditorBrowsable] tells it not to appear in intellisense (only applies to code referencing the dll, not the project, nor code in the same project).

Related

How can I tell if a key was ever defined in a deserialized JSON object in .NET?

I'm using C#/.NET 4.5 to deserialize a JSON object to a native .NET type. The JSON looks like:
{
id: 841,
runningTime: 33.8643736,
title: "Test title"
}
...and the class it deserializes to looks like:
public class Slide
{
public double runningTime
{
get;
set;
}
public string title
{
get;
set;
}
public int id
{
get;
set;
}
}
...using this code to deserialize it:
// given serializer is an instance of JavaScriptSerializer
var slide = serializer.Deserialize<Slide>(json);
This works just fine and I can read properties on the object as if I was directly reading the JSON.
But, what if title is an optional key in the JSON? I can check if it's null after deserializing, but that's not perfect because title could have legitimately been set to null in the JSON itself, and I need to know if the key itself was defined. Using some placeholder value for the title like "UNDEFINED" is also pretty hacky.
So, if I'm using JavaScriptDeserializer to deserialize JSON, how can I tell if a key was defined in the JSON in the first place vs. explicitly set to null?
I assume checking for null is not sufficient since the JSON could contain a null. So you could do this:
public class Slide
{
public bool HasTitle { get; private set; }
public double runningTime
{
get;
set;
}
private string _title;
public string title
{
get { return _title; }
set { _title = value; HasTitle = true; }
}
public int id
{
get;
set;
}
}
Now check "HasTitle" to see if the title property was ever set.
Without changing too much of the rest of your code, you can change the way you define your properties. Nullable<T> gives a good model for a helper structure, but only applies to value types. A version that also works for reference types, except without the special compiler and runtime support (not needed here), is easily made:
public struct Optional<T>
{
private readonly bool hasValue;
private readonly T value;
public Optional(T value) {
this.hasValue = true;
this.value = value;
}
public bool HasValue {
get { return hasValue; }
}
public T Value {
get {
if (!hasValue)
throw new InvalidOperationException();
return value;
}
}
public T GetValueOrDefault() {
return value;
}
public T GetValueOrDefault(T #default) {
return hasValue ? value : #default;
}
}
Add methods as needed.
When you have this, you can then change your class to mark your properties as optional:
public class Slide
{
private Optional<double> _runningTime;
private Optional<string> _title;
private Optional<int> _id;
public double runningTime
{
get { return _runningTime.GetValueOrDefault(); }
set { _runningTime = new Optional<double>(value); }
}
public string title
{
get { return _title.GetValueOrDefault(); }
set { _title = new Optional<string>(value); }
}
public int id
{
get { return _id.GetValueOrDefault(); }
set { _id = new Optional<int>(value);
}
}
You can then determine whether a property setter was ever called, and add support for explicitly unsetting properties:
public bool IsIdSet() {
return _id.HasValue;
}
public void ResetId() {
_id = default(Optional<int>);
}

Dictionary<dynamic, dynamic> Value items can't be accessed. C#

I'm playing around with Dictionaries and the new fancy 4.0 dynamic types inside a dictionary.
I have a Dictionary:
Dictionary<dynamic, dynamic> dynamicDic
And I populate it like this:
dynamicDic.Add("First", new Class1());
dynamicDic.Add("Second", new Class2());
For the sake of testing/practising Class1 and Class2 are quite simple:
public class Class1
{
public string Element { get; set; }
public List<Class2> Class2 { get; set; }
}
public class Class2
{
public string Property { get; set; }
public string Field;
}
I create two other classes that map class1 and class2 and they are virtually the same so ClassMap1 and ClassMap2. I'll just include CalssMap1 though:
public class ClassMap1: BaseClassMap1
{
public ClassMap1()
{
var r = new Class1();
Children = new Dictionary<string, dynamic>
{
{"Element", r.GetType().GetProperty("Element")},
{"Class1", r.GetType().GetProperty("Class1")}
};
Name = "Root";
ObjectType = typeof (Class1);
Parent = "RootElement";
HasParent = false;
HasChildren = true;
IsClass = r.GetType().IsClass;
}
}
And I create a base class: BaseClass1()
public class BaseClass1
{
private String _Name;
public String Name
{
get { return _Name; }
set { _Name = value; }
}
private Type _ObjectType;
public Type ObjectType
{
get { return _ObjectType; }
set { _ObjectType = value; }
}
private String _Parent;
public String Parent
{
get { return _Parent; }
set { _Parent = value; }
}
private Dictionary<string, dynamic> _Children;
public Dictionary<string, dynamic> Children
{
get { return _Children; }
set { _Children = value; }
}
private bool _HasParent;
public bool HasParent
{
get { return _HasParent; }
set { _HasParent = value; }
}
private bool _HasChildren;
public bool HasChildren
{
get { return _HasChildren; }
set { _HasChildren = value; }
}
private bool _IsClass;
public bool IsClass
{
get { return _IsClass; }
set { _IsClass = value; }
}
}
I populate the classes with data, not really important what data :)
Yet when I try to access the values through a Linq statement:
var a = _classObjects.SingleOrDefault(x => x.Key == node.Name).Value;
a only gives me:-
a.Equals(), a.GetType(), a.GetEnumerator() or a.ToString()
I would like to be able to have it do this instead (with intellisense)...
a.Children
a.Name
a.HasParent
etc...
Anyone got any ideas where I'm going wrong?
Oops got that completely wrong... Sorry :|
Edited above...
dynamic classes are all about run-time (NOT compile-time) discovery. How do you expect Intellisense to know what to do?
Using dynamic classes incurs a high performance overhead. I really suggest that you make it: Dictionary<string, dynamic> dynamicDic.
Or define a MyBaseClass and make it: Dictionary<string, MyBaseClass> myDic.

Constructors GetInfo

I am new to C# and am working on classes and understanding them. My problem is I am not understanding how to create a Get to retrieve the private variable _yourname and Set to set the private variable _yourname.
namespace WindowsFormsApplication1
{
class InputClass
{
private string _yourName;
public string _banner;
public virtual void GetInfo();
public InputClass(String _banner)
{
_banner = "Enter your name";
}
}
}
Maybe I am using the wrong function to GetInfo. But I am also wondering when I have the GetInfo if in the () I should write _yourname in it.
In C# there are properties, which have the function of public getter and setter methods in other languages:
class InputClass
{
private string _yourName;
public string _banner;
public InputClass(String _banner)
{
this._banner = _banner;
}
public string YourName
{
get { return _yourName; }
set { _yourName = value; }
}
}
But you can use auto properties, if you want:
class InputClass
{
public InputClass(String _banner)
{
Banner = _banner;
}
public string YourName
{
get; set;
}
public string Banner
{
get; set;
}
}
It sounds like you are trying to provide access to the _yourName field. If so then just use a property
class InputClass {
public string YourName {
get { return _yourName; }
set { _yourName = value; }
}
...
}
Now consumers of InputClass can access it as if it were a read only field.
InputClass ic = ...;
string yourName = ic.YourName;
ic.YourName = "hello";
Note: C# provides a special syntax for simple properties like this which are just meant to be wrappers over private fields. It's named auto-implemented properties
class InputClass {
public string YourName { get; set; }
}
You can override getters and settings using the get and set keywords. For example:
class InputClass
{
private string _yourName;
private string _banner;
public YourName
{
get { return _yourName; }
set { _yourName = value; }
}
public Banner
{
get { return _banner; }
set { _banner = value; }
}
public InputClass(String banner)
{
_banner = banner;
}
}
1.) Use properties instead of members, you get a free accessor (get) and mutator (set).
public string YourName { get; set; }
public string Banner { get; set; }
2.) You can take advantage of the default constructor, and declare it on the fly.
//the old way:
InputClass myClass = new InputClass();
myClass.YourName = "Bob";
myClass.Banner = "Test Banner";
//on the fly:
InputClass myClass = new InputClass()
{
YourName = "Bob",
Banner = "Test Banner"
}

PropertyGrid display class members that are also classes

I have the class PGMain as the SelectedObject in the propertygrid:
[DefaultPropertyAttribute("Basic")]
[Serializable]
public class PGMain
{
private TestClass m_TEST = new TestClass();
[CategoryAttribute("TEST")]
public TestClass TEST
{
get { return m_TEST; }
set { m_TEST = value; }
}
// More members are here
}
Now I would like to expand the members of the TestClass in the PropertyGrid. So I tried the following:
[Serializable]
[DescriptionAttribute("Expand to see the options for the application.")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class TestClass : ExpandableObjectConverter
{
[CategoryAttribute("test-cat"), DescriptionAttribute("desc")]
public string Name = "";
[CategoryAttribute("test-cat"), DescriptionAttribute("desc")]
public object Value = null;
[CategoryAttribute("test-cat"), DescriptionAttribute("desc")]
public bool Include = true;
public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType)
{
if (destinationType == typeof(TestClass))
return true;
return base.CanConvertTo(context, destinationType);
}
}
The result is that there is an expandable-icon in front of the TestClass in the propertygrid but it can not be expanded. What am I missing?
Just to be clear: I can show expandable members of the PGMain class but NOT expandable members of the members of the PGMain class like the Test-member in PGMain.
Edit:
No I have 2 classes NOT 1.
[DefaultPropertyAttribute("Basic")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class fooA
{
private fooB m_TestMember = new fooB();
[Browsable(true)]
[CategoryAttribute("Test category"), DescriptionAttribute("desctiption here")] // <<<<< this one works.
[TypeConverter(typeof(fooB))]
public fooB TestMember
{
get { return m_TestMember; }
set { m_TestMember = value; }
}
}
[DefaultPropertyAttribute("Basic")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class fooB
{
private string m_ShowThisMemberInGrid = "it works"; // <<<<< this doesn NOT work
[CategoryAttribute("Tile"), DescriptionAttribute("desctiption here")]
public string ShowThisMemberInGrid
{
get { return m_ShowThisMemberInGrid; }
set { m_ShowThisMemberInGrid = value; }
}
public override string ToString()
{
return "foo B";
}
}
But I did solve the problem (by coincidence). It appears that public variables are not listed in the propertygrid. It HAVE to be properties with getters and setters. That was the solution. So the above snippet solved the problem. Thanks for your replies anyway :).
Wrong:
[CategoryAttribute("Tile"), DescriptionAttribute("desctiption here")]
public string Name = "";
Good:
private string m_Name = new string();
[CategoryAttribute("Tile"), DescriptionAttribute("desctiption here")]
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
Sorry I misinterpret the question.
You can find more details on these links
http://msdn.microsoft.com/en-us/library/aa302326.aspx#usingpropgrid_topic6a
http://www.codeproject.com/KB/miscctrl/bending_property.aspx
http://msdn.microsoft.com/en-us/library/aa302334.aspx
Hope it helps :)
UPDATE:
I copied the code from here
And modified like this.
public class SamplePerson
{
public string Name
{
get;
set;
}
public Person Person
{
get;
set;
}
}
And in the form I have done something like
SamplePerson h = new SamplePerson();
h.Person = new Person
{
Age = 20,
FirstName = "f",
LastName = "l"
};
this.propertyGrid1.SelectedObject = h;
And its working for me.
Provide Browsable as false for properties you don't want to display in the property grid.
[Browsable(false)]
public bool Include
{
get;set;
}

Many to Many relationship in object design

I have a similar problem like this :
Many to many object to object relation in C#
However, imagine that the Championship would have a "Last Date Played" property (just as an example) that would map to any Participant. In this case, where would that property end up? Is it a must to create an intermediate class? (which i wouldn't want to do) what option do i have? thanks!
One way would be to have an array on each object containing pointers to the other objects either via an dictionary that stores the object as key and date as value (or a custom property class for any number of properties) or using a wrapper class around the object and a plain list, this wrapper should then implement the decorator pattern to allow direct access to the object together with any unique properties.
The wrapper object could use an internal object for the properties that is shared between the oposing wrapper objects for the 2 different objects so that any property is in sync.
Another way would be a separate list of pairs where one is wrapped like the above.
The later makes it easy to loop over all objects.
Here is a code example, it might not be exactly what you need but it might give you the basics of my idea.
void Main()
{
var p = new Player("David");
var c = new Championship("Chess");
p.LinkChampionship(c, DateTime.Now);
p.Dump();
}
// Define other methods and classes here
class Player : Properties {
public virtual String Name {get; set;}
public List<ChampionshipWrapper> champs = new List<ChampionshipWrapper>();
public Player() {
}
public Player(string name) {
Name = name;
}
public void LinkChampionship(Championship champ, DateTime when) {
var p = new Properties(when);
champs.Add(new ChampionshipWrapper(champ, p));
champ.players.Add(new PlayerWrapper(this, p));
}
}
class Championship : Properties {
public virtual String Name { get; set; }
public List<PlayerWrapper> players = new List<PlayerWrapper>();
public Championship(){}
public Championship(string name) {
Name = name;
}
public void LinkPlayer(Player play, DateTime when) {
var p = new Properties(when);
players.Add(new PlayerWrapper(play, p));
play.champs.Add(new ChampionshipWrapper(this, p));
}
}
class Properties {
public virtual DateTime LastPlayed { get; set; }
public Properties() {
}
public Properties(DateTime when) {
LastPlayed = when;
}
}
class PlayerWrapper : Player {
private Player player;
private Properties props;
public PlayerWrapper(Player play, Properties prop) {
this.player = play;
this.props = prop;
}
public override String Name {
get { return this.player.Name; }
set { this.player.Name = value; }
}
public override DateTime LastPlayed {
get { return this.props.LastPlayed; }
set { this.props.LastPlayed = value; }
}
}
class ChampionshipWrapper : Championship {
private Championship champ;
private Properties props;
public ChampionshipWrapper(Championship c, Properties prop) {
this.champ = c;
this.props = prop;
}
public override String Name {
get { return this.champ.Name; }
set { this.champ.Name = value; }
}
public override DateTime LastPlayed {
get { return this.props.LastPlayed; }
set { this.props.LastPlayed = value; }
}
}

Categories