I am trying to find a way to create an instance of a class from the full type name of the class and the json representation of the instance.
var classTypeFullName = "something.type";
var classType = Type.GetType(classTypeFullName);
var instanceJson = "{....}";
var classInstance = JsonConvert.DeserializeObject(instanceJson, classType);
My problem is it is always returning a JObject, i need it to return the instance type. If i knew the type before the code ran I would normal just do the following:
var classInstance = JsonConvert.DeserializeObject<T>(instanceJson);
Can anyone help?
In case you are looking for an answer to something like this.
The C# Core2.2 application was not loading the assembly as it was a dependency of a referenced dll. As such the classType was null and therefore the Deserialization was always coming back as a JObject not the expect type.
Try this one, i did it some time ago.
convert yr Json to dynamic dynamicObj, and have the full assembly name
var type = Type.GetType("something.type");
var obj = Convert.ChangeType(dynamicObj.Result, type);
Related
What I want to achieve is this:
string myClass;
Type type=myClass.ConvertToType()
var object = JsonConvert.DeserializeObject<type>(something);
Is there a function like ConvertToType() ? or is there any other way of doing this?
First, you need to get the assembly the type is in.
var assembly = Assembly.GetExecutingAssembly()
or
var assembly = typeof(anyTypeThatIsInTheAssembly).Assembly;
Then, you get your type that way:
var type = assembly.GetType(typeName);
Finally, you can deserialize the object with this:
JsonConvert.DeserializeObject(something, type);
Suppose I have this code:
public MessageClass(string _paramJson)
{
string[] Messages = new string[] { "MessageA", "MessageB" };
Messages[0] _model0 = JsonConvert.DeserializeObject<Messages[0]>(paramJson);
Messages[1] _model1 = JsonConvert.DeserializeObject<Messages[1]>(paramJson);
}
I know the above won't work, but All I want is to Deserialize the JSON based on a Type passed as string parameter. ie. MessageA, or MessageB.
Even if I define Messages as List<Type> and then do Messages.Add(typeof(MessageA)); for instance, how do I get the type later and passed it on to DeserializedObject<here-some-type-from-my-list>(paramJson) ?
Any help appreciated.
For this to work, you'd have to use reflection to convert MessageA and MessageB to a Type object, then use reflection to dynamically create an instance of the generic method for that type so you can invoke it.
For the first part, see the Type.GetType method documentation.
var type = Type.GetType("Namespace.Prefix.Message1, AssemblyName");
You can skip that second part by using the non-generic version of DeserializeObject:
var message = JsonConvert.DeserializeObject(paramJson, type);
Can anyone tell me why I get an error when trying to output"dJson2.Type" in the code below?
string Json1= #"[{'Id':1, 'FirstName':'John', 'LastName':'Smith'}, {'Id':2, 'FirstName':'Jane', 'LastName':'Doe'}]";
dynamic dJson1= JsonConvert.DeserializeObject(Json1);
Console.WriteLine(dJson1.GetType());
Console.WriteLine(dJson1.Type);
string Json2 = #"{'Id':1, 'FirstName':'John', 'LastName':'Smith'}";
dynamic dJson2 = JsonConvert.DeserializeObject(Json2);
Console.WriteLine(dJson2.GetType());
Console.WriteLine(dJson2.Type);
The program dies on the Console.WriteLine(dJson2.Type) statement. The output of the program is...
Newtonsoft.Json.Linq.JArray
Array
Newtonsoft.Json.Linq.JObject
(should say Object here, I think)
Inspecting the local variables, dJson2 has a "Type" property with value "Object".
This is because JObject behaves similarly as System.Dynamic.ExpandoObject. Try to change your example to:
string Json2 = #"{'Id':1, 'FirstName':'John', 'LastName':'Smith'}";
dynamic dJson2 = JsonConvert.DeserializeObject(Json2);
dJson2.Type = "mynewfield";
Console.WriteLine(dJson2.GetType());
Console.WriteLine(dJson2.Type);
If you want to get property of underlying type you need to cast it (to JToken or JObject), otherwise requested property will be searched in
IDictionary<string, JToken> that JObject implements.
This example may help:
dynamic oobj = new JObject();
oobj.Type = "TEST";
Console.WriteLine(oobj.Type);
Console.WriteLine(((JObject)oobj).Type);
I am writing a simple event dispatcher where my events come in as objects with the clr type name and the json object representing the original event (after the byte[] has been processed into the jobject) that was fired. I'm using GetEventStore if anyone wants to know the specifics.
I want to take that clr type to do 2 things:
find the classes that implements IHandles and
call Consume(clr type) on that class
I have managed to get part 1 working fine with the following code:
var processedEvent = ProcessRawEvent(#event);
var t = Type.GetType(processedEvent.EventClrTypeName);
var type = typeof(IHandlesEvent<>).MakeGenericType(t);
var allHandlers = container.ResolveAll(type);
foreach (var allHandler in allHandlers)
{
var method = allHandler.GetType().GetMethod("Consume", new[] { t });
method.Invoke(allHandler, new[] { processedEvent.Data });
}
ATM the issue is that processedEvent.Data is a JObject - I know the type of processedEvent.Data because I have t defined above it.
How can I parse that JObject into type t without doing any nasty switching on the type name?
Use ToObject:
var data = processedEvent.Data.ToObject(t);
or if you have a known type then:
MyObject data = processedEvent.Data.ToObject<MyObject>();
This turned out to be really easy:
method.Invoke(allHandler, new[] { JsonConvert.DeserializeObject(processedEvent.Data.ToString(), t) });
If, for some reason you're stuck on an older package of Newtonsoft Json.NET (pre 4.5.11 circa 2012) and don't have access to the already mentioned JToken.ToObject(Type), you can reuse what it does internally:
var someJObject = ...; // wherever it came from; actually a JToken
var type = typeof(MyExpectedType);
MyExpectedType myObject;
using (var jsonReader = new JTokenReader(someJObject))
myObject = serializer.Deserialize(jsonReader, type);
I mention this only because I've worked on a project that I couldn't just update the Nuget package for Json.NET to the latest version. Also, this has nothing to do with the .NET framework version.
If I have this string list:
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
in which:
- MyObject: the object class
- SetWidth: the property of the object
- int: type of the SetWidth is int
- 10: default value
- 0: object order
- 1: property order
Then how can I construct an object like this:
[ObjectOrder(0)]
public class MyObject:
{
private int _SetWidth = 10;
[PropertyOrder(1)]
public int SetWidth
{
set{_SetWidth=value;}
get{return _SetWidth;}
}
}
So, I would like have something like this:
Object myObject = ConstructAnObject(myObjectString);
and the myObject is an instance of MyObject. Could it be possible in C#?
Thanks in advance.
I think you better use the Object Serialization/Deserialization instead of creating a custom method that basically needs to do the same thing
more info at:
http://msdn.microsoft.com/en-us/library/ms233843.aspx
Here is some quick and dirty code to get you started:
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
var info = myObjectString.Split(',');
string objectName = info[0].Trim();
string propertyName = info[1].Trim();
string defaultValue = info[3].Trim();
//find the type
Type objectType = Assembly.GetExecutingAssembly().GetTypes().Where(t=>t.Name.EndsWith(objectName)).Single();//might want to redirect to proper assembly
//create an instance
object theObject = Activator.CreateInstance(objectType);
//set the property
PropertyInfo pi = objectType.GetProperty(propertyName);
object valueToBeSet = Convert.ChangeType(defaultValue, pi.PropertyType);
pi.SetValue(theObject, valueToBeSet, null);
return theObject;
This will find the MyObject, create an object of the proper propertytype, and set the matching property.
If you use C# 4.0, you can use the new dynamic feature.
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
String[] properties = myObjectString.Split(',');
dynamic myObj;
myObj.MyObject = (objtect)properties[0];
myObj.SetWidth = Int32.Parse(properties[1]);
// cast dynamic to your object. Exception may be thrown.
MyObject result = (MyObject)myObj;
I don't quite understand why do you need ObjectOrder and PropertyOrder... Once you have their names you probably don't need them, at least for "deserialization"...
Or please advice what is their role?
You definitely can simply do it via reflection:
Split the string by comma (using myString.Split)
Use reflection to find an object within your application:
Find the type with name = splittedString[0] (enumerate all the assemblies within the domain and all the types within each assembly);
Instantiate the type found (using Activator.CreateInstance)
Find the property by name (Using objectType.GetProperty)
Set the property value (using propertyInfo.SetValue)
Return the object
Assuming you need to generate new types there are two possible ways to do so:
Using Reflection Emit
Using CodeDom provider
I think the simpler solution is CodeDom provider. All needed is to generate the source as a string in memory, and then compile the code and instantiate a new instance with Activator. This is a nice example I just found.
The reason I think that CodeDom provider is simpler is that it has shorter setup - no need to generate dynamic module and assembly and then work with type builder and members builder. In addition, it doesn't require working with IL to generate the getter and setter bodies.
An advantage that reflection emit has is performance - dynamic module can add more types to itself even after one of the types was used. CodeDom provider requires creating all the types at once, otherwise it creates a new assembly each time.