Cast dynamic to specific type - c#

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]

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.

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" );
}

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), () => ......}
};

Related

Declare a variable based on Type returned by GetType [duplicate]

I have a object that contain a value in string and a origin Type that is in a field.
class myclass
{
public string value;
public Type type;
}
myclass s=new myclass();
s.value = "10";
s.type = typeof(int);
Type tt = s.type;
row.Value[ind]= s[0].value as tt; //i have error here
How can i cast an value by that's type.
Basically your scenario is that you want to type cast with the type stored in a variable. You can only do that at runtime like this :
myclass s=new myclass();
s.value = "10";
s.type = typeof(int);
var val = Convert.ChangeType(s.value, s.type);
but since the conversion is done at runtime, you cannot store the variable val in any integeral collection i.e. List<int> or even you cannot do int another = val, coz at complie time, the type is not known yet, and you will have compilation error, again for same obvious reason.
In a little complex scenario, if you had to typecast to a User-Defined dataType and you wanted to access its different properties, you cannot do it as is. Let me demonstrate with few modifications to your code :
class myclass
{
public object value;
public Type type;
}
and you have another:
class myCustomType
{
public int Id { get; set; }
}
now you do :
myclass s = new myclass();
s.value = new myCustomType() { Id = 5 };
s.type = typeof(myCustomType);
var val = Convert.ChangeType(s.value, s.type);
now if you do val.Id, it won't compile. You must retrieve it either by using dynamic keyword or by reflection like below:
var id = val.GetType().GetProperty("Id").GetValue(val);
you can iterate over all the available properties of your customType (class) and retrieve their values.
for retrieving it through dynamic keyword, directly do this:
dynamic val = Convert.ChangeType(s.value, s.type);
int id = val.Id;
and compiler won't cry. (Yes there won't be any intellisense though)
Try this:
row.Value[ind] = Convert.ChangeType(s.value, tt);

Dynamically set INT value to Nullable enum property without explicit type cast

I have a method that populates a DataTable to simple DTO object. To simplify I'll use this example:
public enum Gender : int
{
Male = 1,
Female = 2
}
public class Person
{
//...
public Gender? MyGender { get; set; }
}
static void Main(string[] args)
{
int intValue = 2; // value from DB
var o = new Person();
var prop = o.GetType().GetProperty("MyGender");
prop.SetValue(o, intValue , null); // <- Exception
}
The above throws:
Object of type 'System.Int32' cannot be converted to type 'System.Nullable`1[Test.Program+Gender]'.
If I declare MyGender as Gender (not Nullable) everything works fine.
It also works if I use an explicit Cast prop.SetValue(o, (Gender)intValue, null);
BUT, I don't want to (and can't) use the explicit cast: (Gender)intValue because I have no knowledge of the underlying "hard" type when I create the DTO object .
I was hoping for something like (which dose not compile):
var propType = prop.PropertyType;
prop.SetValue(o, (propType)intValue, null);
I also tried:
public static dynamic Cast(dynamic obj, Type castTo)
{
return Convert.ChangeType(obj, castTo);
}
var propType = prop.PropertyType;
prop.SetValue(o, Cast(intValue, propType), null);
Which throws:
Invalid cast from 'System.Int32' to
'System.Nullable`1[[Test.Program+Gender...]
I am at dead end. what are my options?
.NET Framework 4.6.2
This is the best I can come up with. There's an explicit check to see whether the property being assigned to is nullable, but I don't think you can avoid that.
public static void Main(string[] args)
{
int intValue = 2; // value from DB
var o = new Person();
var prop = o.GetType().GetProperty("MyGender");
// Check whether the property is a nullable. If it is, get the type of underling enum
// Otherwise, get the type of the enum directly from the property
var enumType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
// Convert the int to the enum type
var convertedValue = Enum.ToObject(enumType, intValue);
prop.SetValue(o, convertedValue , null);
}
Of course, bad things will happen if the property being assigned isn't an enum. var convertedValue = enumType.IsEnum ? Enum.ToObject(enumType, intValue); : intValue; would avoid that, if you needed it.
A "creative" option to consider is:
var o = new Person();
o.MyGender = 0;
o.MyGender += intValue;
This looks odd, but it does work since the constant 0 has a built-in implicit cast to enum (which other numbers do not).
So, you set it to 0, and then increment it to the actual number you are interested in. A key benefit here is you don't take the performance hit (and / or lack of type safety) of using reflection. You may want to add a comment to the code as to why you are doing it as well. ;)

Cast from unknown type in c#

I have a object that contain a value in string and a origin Type that is in a field.
class myclass
{
public string value;
public Type type;
}
myclass s=new myclass();
s.value = "10";
s.type = typeof(int);
Type tt = s.type;
row.Value[ind]= s[0].value as tt; //i have error here
How can i cast an value by that's type.
Basically your scenario is that you want to type cast with the type stored in a variable. You can only do that at runtime like this :
myclass s=new myclass();
s.value = "10";
s.type = typeof(int);
var val = Convert.ChangeType(s.value, s.type);
but since the conversion is done at runtime, you cannot store the variable val in any integeral collection i.e. List<int> or even you cannot do int another = val, coz at complie time, the type is not known yet, and you will have compilation error, again for same obvious reason.
In a little complex scenario, if you had to typecast to a User-Defined dataType and you wanted to access its different properties, you cannot do it as is. Let me demonstrate with few modifications to your code :
class myclass
{
public object value;
public Type type;
}
and you have another:
class myCustomType
{
public int Id { get; set; }
}
now you do :
myclass s = new myclass();
s.value = new myCustomType() { Id = 5 };
s.type = typeof(myCustomType);
var val = Convert.ChangeType(s.value, s.type);
now if you do val.Id, it won't compile. You must retrieve it either by using dynamic keyword or by reflection like below:
var id = val.GetType().GetProperty("Id").GetValue(val);
you can iterate over all the available properties of your customType (class) and retrieve their values.
for retrieving it through dynamic keyword, directly do this:
dynamic val = Convert.ChangeType(s.value, s.type);
int id = val.Id;
and compiler won't cry. (Yes there won't be any intellisense though)
Try this:
row.Value[ind] = Convert.ChangeType(s.value, tt);

Invalid cast exception generics

I'm having this issue, I'm using reflection to pull properties from a class but the problem is reflection returns them as an object and I can't get it into my actual type.
Take for example, if this is the class:
public class Row<T>
{
public static explicit operator Row<object>(Row<T> o)
{
return new Row<object>
{
Name = o.Name,
Value = o.Value
};
}
public string Name { get; set; }
public T Value { get; set; }
}
Casting from one say Row<bool> to Row<object> works:
var a = new Row<bool>
{
Name = "Foo",
Value = true
};
var b = (Row<object>)a; // Works
But when I try to go from object to Row<object> it seems to ignore my explicit operator and throw a System.InvalidCastException:
var c = (object) a; // Simulate getting from reflection
var d = (Row<object>) c; // System.InvalidCastException
What am I missing?
Use dynamic instead of object to force runtime real type check:
var c = (dynamic)a;
var d = (Row<object>)c; // Works fine
It will call your Row<T> -> Row<object> cast operator.
The problem here is that casting does not look for a conversion operator unless one is defined on the static type of the value you are trying to cast. In your example the static type of c is object and object neither derives from nor has a conversion operator to Row<object>, resulting in the runtime exception.
It looks like this problem can be easily sidestepped with a better design.
You want to treat any type of Row<T> as a Row<object> and the conversion operator does nothing more than work around the fact that these types are not hierarchically related. So why not make them related and avoid the problem in the first place?
For example:
public abstract class Row
{
public string Name { get; set; }
public object Value { get; protected set; }
}
public class Row<T> : Row
{
public new T Value
{
get { return (T)base.Value; }
set { base.Value = value; }
}
}
This seems to do what you want:
The casting problem is solved because you can now cast any type of Row<T> to the base class Row (which takes over the responsibilities of Row<object> in your initial design) and easily access Name and Value no matter what type the Value is.
The Row.Value setter is protected so you cannot cast a Row<int> to Row and make Value e.g. a string from outside, maintaining type safety.
You can accomplish this with reflection:
public class RowHelper
{
public static Row<object> LoadRow(object o)
{
var type = o.GetType();
return new Row<object>
{
Name = (string)type.InvokeMember("Name", BindingFlags.GetProperty, null, o, null),
Value = type.InvokeMember("Value", BindingFlags.GetProperty, null, o, null)
};
}
}
You would call this with:
var d = RowHelper.LoadRow(c);

I need to get a value of specific object's property, but don't know the type of the object

I have got an c# object and I don't know the type of this object. (i.e. object o)
What I know is that this object has a member called 'ID' of type int.
I wanted to get the value of this property but I am not good enough with reflection...
I can get a type and members of this object:
Type type = obj.GetType();
System.Reflection.MemberInfo[] member = type.GetMember("ID");
...but don't know what to do next :-)
Thanks for help in advance
Mariusz
Is this a public property? Is so then the easiest route is to use dynamic
int value = ((dynamic)obj).ID;
You can use:
Type type = obj.GetType();
PropertyInfo property = type.GetProperty("ID");
int id = (int) property.GetValue(obj, null);
Use PropertyInfo because you know it's a property, which makes things easier
Call GetValue to get the value, passing in obj as the target of the property and null for indexer arguments (as it's a property, not an index)
Cast the result to int as you already know it's going to be an int
Jared's suggestion of using dynamic is good too, if you're using C# 4 and .NET 4, although to avoid all the brackets I'd probably write it as:
dynamic d = obj;
int id = d.ID;
(unless you needed it in a single expression for some reason).
Can you use C# 4 ? In that case, you can use dynamic:
dynamic dyn = obj;
int id = dyn.ID;
public class TestClass
{
public TestClass()
{
// defaults
this.IdField = 1;
this.IdProperty = 2;
}
public int IdField;
public int IdProperty { get; set; }
}
// here is an object obj and you don't know which its underlying type
object obj = new TestClass();
var idProperty = obj.GetType().GetProperty("IdProperty");
if (idProperty != null)
{
// retrieve it and then parse to int using int.TryParse()
var intValue = idProperty.GetValue(obj, null);
}
var idField = obj.GetType().GetField("IdField");
if (idField != null)
{
// retrieve it and then parse to int using int.TryParse()
var intValue = idField.GetValue(obj);
}

Categories