Basically, what I want to do is loop over the list of properties on a class, and where they are a particular type I will check a property of that owned property, then set another property to true.
I wrote the code below to illustrate what I want to do, however it will not compile because it says cannot convert type System.Reflection.PropertyInfo to type ThermodynamicState. In addition it gives the warning that the given expression is never of ThermodynamicState type.
How do I convert each property in the list of properties reflection gives into an object of that type?
public void BasisChanged()
{
foreach (ThermodynamicProperty thermoProperty in this.GetType().GetProperties().Where(p => p.PropertyType is ThermodynamicProperty && !((ThermodynamicProperty)p.PropertyType).IsBasis))
{
thermoProperty.BasisChanged = true;
}
}
I believe, you are trying something like the following:
public void BasisChanged()
{
foreach (var p in GetType().GetProperties().Where(p => typeof(ThermodynamicProperty).IsAssignableFrom(p.PropertyType)))
{
var value = (ThermodynamicProperty)p.GetValue(this);
if (!value.IsBasis)
value.BasisChanged = true;
}
}
You have to check the property's type via PropertyType. IsAssignableFrom() checks if objects of this type can be assigned to a ThermodynamicProperty variable. Then you get the current object with GetValue() and set the BasisChanged property.
Note that this assumes ThermodynamicProperty to be a reference type. If it is a value type, you have to set it back after changing it.
foreach (PropertyInfo p in this.GetType().GetProperties().Where(p => p.PropertyType == typeof(ThermodynamicProperty)))
{
ThermodynamicProperty propertyObject = (ThermodynamicProperty)p.GetValue(this);
if (!propertyObject.IsBasis)
{
propertyObject.BasisChanged = true;
}
}
This is my code
public virtual T GetRepository<T>()
where T : class
{
var type = typeof ( T );
var properties = this.GetType().GetProperties();
foreach ( var property in properties )
{
var name = property.Name;
if ( name == type.Name )
{
var a = this.GetType().GetProperty(name) as T;
return a;
}
}
return null;
}
The objective is to return the generic type T. First I get the properties of the class, and then I loop over the properties in hopes of finding a property name which has the same name as the type T.
This works okay in my case because the properties are all of the form Interface<FooRepository> FooRepository { get; set; } so I need only compare the two.
This method is inside a class. The problem is that a will change to null immediately after the statement as T. What can be done?
If you want the value of the property you could try using the GetValue method and replace this:
var a = this.GetType().GetProperty(name) as T;
with this:
var a = property.GetValue(this) as T;
Also it is not quite clear what exactly is the purpose of such method but this condition here looks shaky:
if (name == type.Name)
The name of the property should equal the name of the generic type parameter. Is it really what is needed here?
GetProperty method will always return ProprtyInfo type so unless T is PropertyInfo a will be always null.
Please have a look at below code.
Issue is at following loc.
MyClassExample obj2 = lstObjectCollection[0] as type;
I want to type cast an object of list to its type. But type will be given at runtime.
How can we cast an object, knowing its type at runtime?
class RTTIClass
{
public void creatClass()
{
// Orignal object
MyClassExample obj1 = new MyClassExample {NUMBER1 =5 };
// Saving type of original object.
Type type = typeof(MyClassExample);
// Creating a list.
List<object> lstObjectCollection = new List<object>();
// Saving new object to list.
lstObjectCollection.Add(CreateDuplicateObject(obj1));
// Trying to cast saved object to its type.. But i want to check its RTTI with type and not by tightly coupled classname.
// How can we achive this.
MyClassExample obj2 = lstObjectCollection[0] as type;
}
public object CreateDuplicateObject(object originalObject)
{
//create new instance of the object
object newObject = Activator.CreateInstance(originalObject.GetType());
//get list of all properties
var properties = originalObject.GetType().GetProperties();
//loop through each property
foreach (var property in properties)
{
//set the value for property
property.SetValue(newObject, property.GetValue(originalObject, null), null);
}
//get list of all fields
var fields = originalObject.GetType().GetFields();
//loop through each field
foreach (var field in fields)
{
//set the value for field
field.SetValue(newObject, field.GetValue(originalObject));
}
// return the newly created object with all the properties and fields values copied from original object
return newObject;
}
}
class MyClassExample
{
public int NUMBER1 {get; set;}
public int NUMBER2{get; set;}
public int number3;
public int number4;
}
The pattern I normally use is the is operator which will tell whether your object is a particular type. This will work if you already kinda sorta know which objects you will be using
Object myObject
if(myObject is Obj1)
// do obj1 stuff
else if(myObject is Obj2)
// do stuff with obj2
I've never had it come up where i had to operate on more than a handful of different types and treat them all specially, so this is what i normally do.
You can easily get all the objects of a certain type in the list using the OfType<T> extension method:
lstObjectCollection.OfType<MyClassExample>()
If the type is only known at runtime, you can do this:
lstObjectCollection.Where(o => o.GetType() == type)
We have a property of type long? that gets filled with an int.
This works fine when i just set the property directly obj.Value = v; but when i try and set the property through reflection info.SetValue(obj, v, null); it gives me a the following exception:
Object of type 'System.Int32' cannot be converted to type 'System.Nullable`1[System.Int64]'.
This is a simplified scenario:
class TestClass
{
public long? Value { get; set; }
}
[TestMethod]
public void TestMethod2()
{
TestClass obj = new TestClass();
Type t = obj.GetType();
PropertyInfo info = t.GetProperty("Value");
int v = 1;
// This works
obj.Value = v;
// This does not work
info.SetValue(obj, v, null);
}
Why does it not work when setting the property through reflection while it works when setting the property directly?
Check full article : How to set value of a property using Reflection?
full code if you are setting value for nullable type
public static void SetValue(object inputObject, string propertyName, object propertyVal)
{
//find out the type
Type type = inputObject.GetType();
//get the property information based on the type
System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propertyName);
//find the property type
Type propertyType = propertyInfo.PropertyType;
//Convert.ChangeType does not handle conversion to nullable types
//if the property type is nullable, we need to get the underlying type of the property
var targetType = IsNullableType(propertyType) ? Nullable.GetUnderlyingType(propertyType) : propertyType;
//Returns an System.Object with the specified System.Type and whose value is
//equivalent to the specified object.
propertyVal = Convert.ChangeType(propertyVal, targetType);
//Set the value of the property
propertyInfo.SetValue(inputObject, propertyVal, null);
}
private static bool IsNullableType(Type type)
{
return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
}
you need to convert value like this i.e you need to convert value to your property type like as below
PropertyInfo info = t.GetProperty("Value");
object value = null;
try
{
value = System.Convert.ChangeType(123,
Nullable.GetUnderlyingType(info.PropertyType));
}
catch (InvalidCastException)
{
return;
}
propertyInfo.SetValue(obj, value, null);
you need to do this because you cannot convert any arbirtary value to given type...so you need to convert it like this
When you write:
obj.Value = v;
the compiler knows how to do the proper casting for you and actually compiles
obj.Value = new long?((long) v);
When your use reflection there is no compiler to help you.
Because the type long has an implicit conversion method.
6.1.2 Implicit numeric conversions
You can see implicit conversion method as hidden method that exist behind the = symbol.
It also work with nullable type:
int i = 0;
int? j = i; // Implicit conversion
long k = i; // Implicit conversion
long? l = i; // Implicit conversion
But going the other way around doesn't work, because no implicit conversion exist to pass a null to a non-null:
int? i = 0;
int j = i; // Compile assert. An explicit conversion exit...
int k = (int)i; // Compile, but if i is null, you will assert at runtime.
You don't have to explicitly convert a int to a int?... or a long?.
However, when you use reflection, you are bypassing implicit conversion and assign directly the value to the property. This way, you have to convert it explicitly.
info.SetValue(obj, (long?)v, null);
Reflection skip all the sweet stuff hidden behind =.
Consolidating and expanding on Pranay Rana's answer to handle enums as suggested by SilverNinja (and answered by thecoop) and put accumulated the learnings in one place. This is a little more copy/pastable.;
private void SetApiSettingValue(object source, string propertyName, object valueToSet)
{
// find out the type
Type type = source.GetType();
// get the property information based on the type
System.Reflection.PropertyInfo property = type.GetProperty(propertyName);
// Convert.ChangeType does not handle conversion to nullable types
// if the property type is nullable, we need to get the underlying type of the property
Type propertyType = property.PropertyType;
var targetType = IsNullableType(propertyType) ? Nullable.GetUnderlyingType(propertyType) : propertyType;
// special case for enums
if (targetType.IsEnum)
{
// we could be going from an int -> enum so specifically let
// the Enum object take care of this conversion
if (valueToSet != null)
{
valueToSet = Enum.ToObject(targetType, valueToSet);
}
}
else
{
// returns an System.Object with the specified System.Type and whose value is
// equivalent to the specified object.
valueToSet = Convert.ChangeType(valueToSet, targetType);
}
// set the value of the property
property.SetValue(source, valueToSet, null);
}
private bool IsNullableType(Type type)
{
return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
}
I also ran into this problem when creating new objects reflectively.
This is how not to do it:
var newOne = Activator.CreateInstance(srcProp.GetType());
srcProp.SetValue(newGameData, newOne, null);
And this is how to do it:
var newOne = Activator.CreateInstance(srcProp.PropertyType);
srcProp.SetValue(newGameData, newOne, null);
This is old thread. But solutions in this page didn't work. I did some adjust and works great (in .netcore 2.0)!
obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
if (!object.Equals(this.reader[prop.Name], DBNull.Value))
{
if (prop.PropertyType.Name.Contains("Nullable"))
{
prop.SetValue(obj, Convert.ChangeType(this.reader[prop.Name], Nullable.GetUnderlyingType(prop.PropertyType)), null);
}
else
{
prop.SetValue(obj, this.reader[prop.Name], null);
}
}
}
var properties = propTypes.GetProperty(attribute);
TypeCode typeCode = Type.GetTypeCode(properties.PropertyType);
switch (typeCode)
{
case TypeCode.Int32:
properties.SetValue(m, Convert.ToInt32(value.AsPrimitive().Value));
break;
case TypeCode.Int64:
properties.SetValue(m, Convert.ToInt64(value.AsPrimitive().Value));
break;
}
You may try something like this that worked for me for conversion to double?:
Type propType = propInfo.PropertyType;
if (propType.AssemblyQualifiedName.StartsWith("System.Nullable`1[[System.Double"))
{
if (dataRow[column.ColumnName] == DBNull.Value)
{
propInfo.SetValue(obj, null, null);
}
else
propInfo.SetValue(obj, (double?)dataRow[column.ColumnName], null);
}
else
propInfo.SetValue(obj, dataRow[column.ColumnName], null);
How can I read the properties of an object that contains an element of array type using reflection in c#. If I have a method called GetMyProperties and I determine that the object is a custom type then how can I read the properties of an array and the values within. IsCustomType is method to determine if the type is custom type or not.
public void GetMyProperties(object obj)
{
foreach (PropertyInfo pinfo in obj.GetType().GetProperties())
{
if (!Helper.IsCustomType(pinfo.PropertyType))
{
string s = pinfo.GetValue(obj, null).ToString();
propArray.Add(s);
}
else
{
object o = pinfo.GetValue(obj, null);
GetMyProperties(o);
}
}
}
The scenario is, I have an object of ArrayClass and ArrayClass has two properties:
-string Id
-DeptArray[] depts
DeptArray is another class with 2 properties:
-string code
-string value
So, this methods gets an object of ArrayClass. I want to read all the properties to top-to-bottom and store name/value pair in a dictionary/list item. I am able to do it for value, custom, enum type. I got stuck with array of objects. Not sure how to do it.
Try this code:
public static void GetMyProperties(object obj)
{
foreach (PropertyInfo pinfo in obj.GetType().GetProperties())
{
var getMethod = pinfo.GetGetMethod();
if (getMethod.ReturnType.IsArray)
{
var arrayObject = getMethod.Invoke(obj, null);
foreach (object element in (Array) arrayObject)
{
foreach (PropertyInfo arrayObjPinfo in element.GetType().GetProperties())
{
Console.WriteLine(arrayObjPinfo.Name + ":" + arrayObjPinfo.GetGetMethod().Invoke(element, null).ToString());
}
}
}
}
}
I've tested this code and it resolves arrays through reflection correctly.
You'll need to retrieve the property value object and then call GetType() on it. Then you can do something like this:
var type = pinfo.GetGetMethod().Invoke(obj, new object[0]).GetType();
if (type.IsArray)
{
Array a = (Array)obj;
foreach (object arrayVal in a)
{
// reflect on arrayVal now
var elementType = arrayVal.GetType();
}
}
FYI -- I pulled this code from a recursive object formatting method (I would use JSON serialization for it now).