miechooy
miechooy

Reputation: 3422

Cast dynamic to specific type

I am retrieving JSON with different object type in one part. I made this part as dynamic.

I need to get data from this object so I created class which looks the same as the dynamic data like below:

public class SpecificObject1
{
    public string Title{get; set;}
    public object[] ViewElements{get; set}
    public object AnyAttributes{get; set;}
}

Here is how I want to convert it to this specific object:

  var @switch = new Dictionary<Type, Action> {
                { typeof(x), () =>  jsonObj.Some = jsonObj.Some as SpecificObject1},
                { typeof(y), () =>  ......}
            };

Casting with as returns null.

EDIT: Changed properties to real one

dynamic contains:

AnyAttributes: {object}
Title: "title"
ViewElements: object[0]

Upvotes: 7

Views: 34933

Answers (3)

trueboroda
trueboroda

Reputation: 2890

You can use a Slapper.AutoMapper functionality. Use MapDynamic() method for your needs.

public class Person
{
    public int Id;
    public string FirstName;
    public string LastName;
}

[Test]
public void Can_Map_Matching_Field_Names_Using_Dynamic()
{
    // Arrange
    dynamic dynamicPerson = new ExpandoObject();
    dynamicPerson.Id = 1;
    dynamicPerson.FirstName = "Clark";
    dynamicPerson.LastName = "Kent";

    // Act
    var person = Slapper.AutoMapper.MapDynamic<Person>( dynamicPerson ) as Person;

    // Assert
    Assert.NotNull( person );
    Assert.That( person.Id == 1 );
    Assert.That( person.FirstName == "Clark" );
    Assert.That( person.LastName == "Kent" );
}

Upvotes: 3

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37095

You can´t change the type of an object - be it dynamic or any other compile-time type. Thus even if you assign jsonObj.Some as SpecificObject1 to jsonObj.Some you can´t change its compiletime type (probably dynamic in your case which is a compiletime-type).

This would imply you could to this:

int a = 3;
a = a as string;

Which is obvious non-sense. a is of type int which can´t be changed. So even if you *could cast a to a string you can´t assign the result (which would be of type sting) to a because a actually is of type int.

The same applies to an instance of dynamic:

dynamic b = a as Bar;

This will still evaluate to b being of type dynamic. However if a was a Bar-instance before, the runtime-type of b surely is Bar as well. Anyway you don´t get anything by this cast as the compile-time-type of b is still dynamic - making it a no-op.

EDIT: In order to get a compile-time type which you can use you have to create a new instance of SpecificType based on jsonObj.Some:

var newValue = new SpecificObject {
    Title = jsonObj.Some.Title,
    ViewElements = jsonObj.Some.ViewElements,
    AnyAttributes = jsonObj.Some.AnyAttributes 
}

However you can´t assign this to jsonObj.Some and expect the latter to be of type SpecificObject at compile-time. Anyway as it already is dynamic you can do everything you want with it, for instance set its Title:

jsonObj.Some.Title = "NewTitle";

You won´t need any cast for this.

Upvotes: 7

sujith karivelil
sujith karivelil

Reputation: 29036

When you use as for casting, it Assigns null to the destination if the source is null or it is not convertible. So you cannot use it with value types. Where as this(jsonObj.Some = (SpecificObject1)jsonObj.Some) will throws InvalidCastException if either source is null or not convertible.

var @switch = new Dictionary<Type, Action> {
                { typeof(x), () =>  jsonObj.Some = (SpecificObject1)jsonObj.Some },
                { typeof(y), () =>  ......}
            };

Upvotes: 0

Related Questions