Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a dynamic object to a concrete object in .NET C#

As you saw from the title, I need convert this object:

    object obj = new{
       Id = 1,
       Name = "Patrick"
    };

To specific class instance.

To be more clear, here is an example for you guys:

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }

    }

    public class Scholar
    {
        public int UniqueId { get; set; }
        public string FullName { get; set; }

    }

I have two classes Student and Scholar. I cant figure out a way to properly write an algorithm of conversion to specific type.

In my opinion, pseudo code should look like this :

if (obj.CanBeConverted<Student>()) {
   //should return this if statement

   obj = ConvertToType<Student>(o);

   // after this method obj type should change to Student
} else if (obj.CanBeConverted<Scholar>()) {

   //at current example wont reach this place
  obj = ConvertToType<Scholar>(o);

  // after this method obj type should change to Scholar
}

It this possible to program in some way ?


I surfed the net and found this example : https://stackoverflow.com/a/17322347/8607147

However this solution always tries to convert / deserialize object or dynamic type to concrete object.

like image 229
Androidmuster Avatar asked Apr 25 '18 12:04

Androidmuster


People also ask

Can we use dynamic as return type in C#?

Yes there are ways by which you can deliver different objects on run time and dynamic is one of those solution. Today, we will understand how to use dynamic keyword to return a whole different object on runtime. You can even change the return type based on your input.

What is the difference between dynamic and object in C#?

Object is useful when we don't have more information about the data type. Dynamic is useful when we need to code using reflection or dynamic languages or with the COM objects and when getting result out of the LinQ queries.

What is ExpandoObject in C#?

The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject. sampleMember instead of more complex syntax like sampleObject.

What is dynamic type C#?

In C# 4.0, a new type is introduced that is known as a dynamic type. It is used to avoid the compile-time type checking. The compiler does not check the type of the dynamic type variable at compile time, instead of this, the compiler gets the type at the run time.


1 Answers

You can do it by using Json.Net Schema and Json.Net, check bellow how I did it:

  class Program
  {
    static void Main(string[] args)
    {
      var o = new
      {
        Id = 1,
        Name = "Patrick",
        Courses = new[] { new { Id = 1, Name = "C#" } }
      };

      Student student = null;
      Scholar scholar = null;

      if (o.CanBeConverted<Student>())
        student = o.ConvertToType<Student>();
      else if (o.CanBeConverted<Scholar>())
        scholar = o.ConvertToType<Scholar>();

      System.Console.WriteLine(student?.ToString());
      System.Console.WriteLine(scholar?.ToString());

      System.Console.ReadKey();
    }
  }

  public static class ObjectExtensions
  {
    public static bool CanBeConverted<T>(this object value) where T : class
    {
      var jsonData = JsonConvert.SerializeObject(value);
      var generator = new JSchemaGenerator();
      var parsedSchema = generator.Generate(typeof(T));
      var jObject = JObject.Parse(jsonData);

      return jObject.IsValid(parsedSchema);
    }

    public static T ConvertToType<T>(this object value) where T : class
    {
      var jsonData = JsonConvert.SerializeObject(value);
      return JsonConvert.DeserializeObject<T>(jsonData);
    }
  }

  public class Student
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public Courses[] Courses { get; set; }

    public override string ToString()
    {
      return $"{Id} - {Name} - Courses: {(Courses != null ? String.Join(",", Courses.Select(a => a.ToString())) : String.Empty)}";
    }
  }

  public class Courses
  {
    public int Id { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
      return $"{Id} - {Name}";
    }
  }

  public class Scholar
  {
    public int UniqueId { get; set; }
    public string FullName { get; set; }

    public override string ToString()
    {
      return $"{UniqueId} - {FullName}";
    }
  }

The solution is basically by generating a JSON Schema from your desired object and check if the new data que fit this shema.

like image 192
Rodrigo Avatar answered Sep 21 '22 04:09

Rodrigo