How to deserialize a class heriting a generic interface dynamically [duplicate] - c#

This question already has answers here:
Deserialize collection of interface-instances?
(9 answers)
Closed 3 years ago.
I have multiple classes extended from an interface and I have a json editor to edit each of those classes that I have in a List, "I" being my interface
So let's say I have the variable of the current class which properties have been edited
I now have the new Json that contains the new values
How do I deserialize the new json according to the current class being edited?
I have access to the class name if that can help but I can't find a way to do
I have tried .GetType() for the current selected Class : IRule and reflector
class RuleOne : IRule
{
public bool variable{ get; set; }
public int num;
}
class RuleTwo : IRule
{
public bool variable{ get; set; }
public string name;
}
List<IRule> Rules = new List<IRule>;
Rules.Add(new RuleOne());
Rules.Add(new RuleTwo());
string json = JsonConvert.SerializeObject(Rules[0]);
// How do I deserialize the json string into Rules[0] ?
I expect the modified json to be stored in it's original class

You need to help serializer to remember the types.
Check this thread for more details.

Type type = Type.GetType($"{EditorRule.GetType().Namespace}.{EditorRule.GetType().Name}"); // Can be replaced dynamically
EditorRule = (IRule)JsonConvert.DeserializeObject(JsonText, type);
This worked for me, I didn't know you could also pass a "dynamic" type as an argument to JsonConvert.Deserialize()

Related

Custom class out of existing one [duplicate]

This question already has answers here:
Comparing Object properties using reflection
(5 answers)
Closed 3 years ago.
I would like to know if there is a way to create a custom class out of an existing class in this manner:
original class:
public class Person
{
string name;
}
later in code:
var diffPerson = CreateDiffClass<Person>();
diffPerson.name.Value = "name";
diffPerson.name.Changed = false;
this diffPerson is not of Person type, instead it is custom created one, that for every variable in Person have one in itself so that the new variable is a tuple where T is the type of the variable.
I want it to create a system for comparing 2 instances of the same class. one old instance and one new and save the new value and if it changed
I don't really know how to describe it except showing in this example so I hope it is understandable..
I want this to be generic and work on any given class
Thanks
You can declare a generic class like this
public class CustomValue<T>
{
public T Value { get; set; }
public bool Changed { get; set; }
}
and then use it like this
public class Person
{
public CustomValue<string> Name;
}
later in code
var diffPerson = new Person();
diffPerson.Name = new CustomValue<string>();
diffPerson.Name.Value = "name";
diffPerson.Name.Changed = false;

initiated a property with different classes from the constructor [duplicate]

This question already has answers here:
Convert List<DerivedClass> to List<BaseClass>
(13 answers)
Closed 3 years ago.
I have a class that have a property (SearchResults) that need to be List<T>, where T is one of my search classes depend on a condition
public class SearchGeneralResponse : ActionResponse
{
public IList<ISearchRecord> SearchResults { get; set; }
public SearchGeneralResponse(MbsObjectType searchType)
{
if(searchType == MbsObjectType.SourceRepo) SearchResults = new List<SearchRecord>();
if(searchType == MbsObjectType.BuildConfiguration) SearchResults = new List<SearchRecordBuild>();
}
}
I can cast new SearchRecord to ISearchRecord. But when I do it with list
this.SearchResults = new List<SearchRecord>();
I get this error:
Cannot implicitly convert type System.Collections.Generic.List 'SearchRecord' to System.Collections.Generic.List 'ISearchRecord'
Here's my interface:
public interface ISearchRecord
{
}
And one of the derived classes:
public class SearchRecord : ISearchRecord
{
public string Name { get; set; }
public string Summary { get; set; }
}
How can I create a List<T> property that can be initialized to a list of a class depending on a certain condition?
Add a cast to your initializer:
this.SearchResults = new List<SearchRecord>().Cast<ISearchRecord>().ToList();
Generics provide compile-time type safety, but in this case you're trying to tell the compiler that it should just trust you that there won't be run-time problems. Its job is to not trust you :)
Consider what would happen if this assignment were allowed and you did this:
IList<ISearchRecord> results; // results is of type IList<ISearchRecord>
results = new List<SearchRecord>(); // but it holds a value of type List<SearchRecord>
results.Add(new SomeOtherSearchRecord()); // ERROR
Since the property SearchResults is of type IList<ISearchRecord>, any code which uses that property can assign any implementation of ISearchRecord to an element of that list. So it needs to always be ISearchRecord and not a more specific implementing type.
Step back and consider the semantics of what your code needs to do. Should SearchResults support any implementation of ISearchRecord? If it's always going to be assigned from SearchRecord then make it that specific type:
public IList<SearchRecord> SearchResults { get; set; }
Or, if it needs to be a list of ISearchRecord (so it can support other implementations) then you'd have to create the list of that type:
this.SearchResults = new List<ISearchRecord>();
Edit: Also, if your new List<>() is just a contrived example and you're actually getting the list from somewhere else, you still need to create a new list. Fortunately the references within that list can still be to the same objects, but the list itself needs to be the correct compile-time type. You could achieve this with:
this.SearchResults = someOtherList.Cast<ISearchRecord>().ToList();
This would create a new list object, of the correct type, containing the same elements as someOtherList.

Serialize and deserialize a hierarchy of a C# class to Json [duplicate]

This question already has answers here:
Using Json.NET converters to deserialize properties
(9 answers)
Closed 6 years ago.
Is there a way to serialize and then deserialize a class that has a member variable of unknown type that could be either be a simple value type or an instance of the containing class itself ?
public class A
{
public dynamic Value { get; set; }//Value could be int or type A for example
}
public static class ASerializer
{
public static string ToJson(A table)
{
return JsonConvert.SerializeObject(table);//using Json.Net
}
public static A FromJson(string json)
{
return JsonConvert.DeserializeObject<A>(json);
}
}
public class Tests
{
public static void TestASerialization()
{
var a = new A() { Value = 1 };
var aa = new A { Value = a };
var aaa = new A { Value = aa };
var json = ASerializer.ToJson(aaa);
var aaa2 = ASerializer.FromJson(json);
var aa2 = (A)aaa2.Value; //throws
}
}
if I serialize and then deserialize aaa - I can't cast the Value of the deserialized aaa back to type A I get:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : Cannot convert type 'Newtonsoft.Json.Linq.JObject' to
'A'
Any suggestions on handling this nested hierarchy elegantly, without resorting to hand coding ?
Seems to work with just one instance of A with Value of type A.
You aren't casting what you think you're casting.
In this case, you're actually casting the Value property to A. You need to wrap the aaa2 instance in params with the cast before accessing the property.
var aa2 = ((A)aaa2).Value;
Dynamic is a compiler hack mostly, I would recommend generics instead.
#David L 's answer is also correct.
public class A<T>
{
public T Value { get; set; }
}

Is there a way to decorate an int property so that it serializes as a string? [duplicate]

This question already has answers here:
How to make JSON.Net serializer to call ToString() when serializing a particular type?
(4 answers)
Closed 3 years ago.
Is it possible to create a decorator for a property of a class of type int so it serializes as a string?
I have
public class MyClass
{
[SerializeAsString] //this is what I want
public int StreetCode { get; set; }
}
so when I call
var jsonRequest = JsonConvert.SerializeObject(myClass);
I want it to output the value between quotes rather than as an int without quotes.
This requires a custom converter based on Newtonsoft.Json.Converter to be created.
Then you would use the converter like so
[JsonConverter(typeof(ToStringConverter))]
public int StreetCode { get; set; }

Deserialize random/unknown types with XmlSerializer [duplicate]

This question already has an answer here:
Deserialize XML To Object using Dynamic
(1 answer)
Closed 8 years ago.
I am using XmlSerializer to communicate with a service. This is not a regular SOAP service, it has its own XML object types. For example, I may ask for a <Capabilities> object, but it may return an <Exception>. So, in other words, I have to deal with random XML document types. I do however, know which types I have to deal with.
What I am trying to do is to find a generic approach to serialize/deserialize these documents. The problem is that the XmlSerializer needs to know the type at creation stage.
These are NOT encapsulated in a common root element, so making a base class and using the [XmlInclude] attribute does NOT work in this case:
[XmlInclude(typeof(Exception))]
[XmlInclude(typeof(Capabilities))]
public abstract class BaseClass
{
public BaseClass()
{
SchemaLocation = "test";
}
[XmlAttribute("schemaLocation")]
public String SchemaLocation { get; set; }
}
[XmlRoot("Exception")]
public class Exception : BaseClass
{
public Exception():base()
{
}
[XmlElement]
public String Message { set; get; }
}
[XmlRoot("Capabilities")]
public class Capabilities : BaseClass
{
public Capabilities() : base()
{}
[XmlElement]
public String ServiceName { set; get; }
}
My solution so far is to probe the root element manually with the XmlReader, and then map it to the correct type before creating an XmlSerializer instance.
Is there any better way of doing this ?
As you mentioned when you request for the service might return . So do you know if an request is made for a type then the service might return only certain types back?
I would have tried XmlSerializer Constructor (Type, Type[])...
Initializes a new instance of the XmlSerializer class that can serialize objects of the specified type into XML documents, and deserialize XML documents into object of a specified type. If a property or field returns an array, the extraTypes parameter specifies objects that can be inserted into the array.

Categories