So, as the heading says, I have an object which is propertyInfo. What I want to get is that property, but I can't seem to find a way to do it.
Firstly I had this method:
public object GetPropertyInfo(object parent, String propertyName)
{
object propInf = null;
PropertyInfo[] propList = parent.GetType().GetProperties();
foreach (PropertyInfo pInf in propList)
{
if (propertyName == pInf.Name)
{
propInf = pInf;
}
}
return propInf;
}
And it works rather well, assuming the supplied 'parent' object is a regular class and not a reflected type.
But some of the properties returned themselves contain properties that I want to access. In these instances, I need to feed the PropertyInfo back into this method and get another PropertyInfo for the property. But if I put a PropertyInfo object into this method, it just returns me a property list of PropertyInfo (as you might imagine).
I have read up on it and it seems that what I may want is the 'GetValue' method of the PropertyInfo class. I'm a little unsure of it though since I can't seem to parse what it is that the method requires.
Even so, I wrote it as such:
public object GetPropertyInfo(object parent, String propertyName)
{
object propInf = null;
object o = null;
if (parent is PropertyInfo)
{
PropertyInfo p = (parent as PropertyInfo);
o = p.GetValue(p, null);
}
else
o = parent;
PropertyInfo[] propList = o.GetType().GetProperties();
foreach (PropertyInfo pInf in propList)
{
if (propertyName == pInf.Name)
{
propInf = pInf;
}
}
return propInf;
}
Obviously I hoped the second one would work. It passes through the 'if' statement fine, acknowledging that it is a PropertyInfo type, but then the next part provides an exception which is the following:
TargetException: Object does not match target type.
Maybe I made a mistake with the 'GetValue' since I'm not entirely familiar with it, but if I could do it without specifying a type, that would be great.
Assuming I understand what you are trying to do:
PropertyInfo represents a property of a class without being aware of the instance of the class whose property is being inspected.
GetValue method, however, can provide you the value of the property for a given instance.
object value = somePropertyInfo.GetValue(someInstance);
// where someInstance is of the type which has someProperty's represented property.
If you want the properties of the Type of the property you are currently inspecting you can use PropertyInfo.PropertyType.GetProperties(); but this will only get you the properties of the Type of the property and not the concrete (maybe derived) Type that it contains.
Related
So, I am interested in getting all properties of a class via reflection ... and all properties of class-type properties (recursively).
I managed to get the first level of properties via reflections with a code like this:
foreach (var property in Target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var foobar = Factory.GetDealer(Target, property.Name);
}
and in the factory:
public static BaseDealer GetDealer(Object obj, string property)
{
var prop = obj.GetType().GetProperty(property);
if (prop == null)
{
return null;
}
if (prop.PropertyType.IsPrimitive)
{
return GetPrimitivDealer(obj, property, Type.GetTypeCode(prop.PropertyType));
}
if (prop.PropertyType.IsClass)
{
return new CompositeDealer(obj, prop);
}
return null;
}
Obviously (in my mind that is), I'd then have something like this in the CompositeDealer:
public CompositeDealer(Object obj, PropertyInfo propInfo)
{
ComponentDealers = new List<BaseDealer>();
Object compProp = propInfo.GetValue(obj); // The new "origin" object for reflection, this does not work
foreach (var property in compProp.GetType().GetProperties())
{
var dealer = Factory.GetDealer(compProp, property.Name);
if (dealer != null)
{
ComponentDealer.Add(dealer);
}
}
}
As noted in the comment, getting the new "base object" for reflection, that is to start the "second level" of reflection does not work, it returns null.
I really struggle at this stage although I came so far and am pretty close (I think).
Help me StackOverflow,
you're my only hope.
Edit:
So, answering the question what the data would look like:
class A {
int primitiveProp {get;}
}
class B {
A compositeProp {get;}
}
If I were to call the Factory on an instance of A, I'd make a PrimitiveDealer.
If we call it on an instance of B, I'd get a CompositeDealer, which in turn has a primitiveDealer.
Also note that I need the actual property object of the passed instance (since I need to manipulate it) rather than a new object.
Instead of calling different functions to get the properties of your object, dependent on the property type, the function should then call itself with an instance of the object we want to get the properties of.
object o = Activator.CreateInstance(property.PropertyType)
Recursively call the function which gets the properties of this object.
Edit: If you instead need the actual object, ensure to cast it to the correct type.
Type compProp = (Type)propInfo.GetValue(obj);
I've writing a small method whose sole purpose is to check if a property is null for a given class. If the property is null, then create a new instance of it. I'm getting stuck on part where I'm actually setting a value:
public static void CheckIfPropertyIsNull<TEntity>(SomeBusinessEntity someBusinessEntity) where TEntity : new()
{
var properties = typeof(SomeBusinessEntity).GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
Type currentType = propertyInfo.PropertyType;
if (currentType == typeof(TEntity))
{
var propertyData = propertyInfo.GetValue(someBusinessEntity, null);
if (propertyData == null)
{
object instance = Activator.CreateInstance(typeof(TEntity));
// And then?
//propertyInfo.SetValue(null, instance);
return;
}
}
}
}
I try to use the SetValue() method but with no luck.
In your SetValue you still have to give the instance of the owner of the property: someBusinessEntity.
object instance = new TEntity();
// And then
propertyInfo.SetValue(someBusinessEntity, instance);
Note that your logic seems odd to me. You are using a generic type to set all properties. Why not use the type of the property?
I was trying to process a generic class with properties that are List<T>. However it does not work when checking the property using IsAssignableFrom.
Code Snippet:
var type = model.GetType();
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
int colorIndex = 0;
foreach (var property in properties)
{
if (typeof(List<>).IsAssignableFrom(property.PropertyType))
{
//codes here
}
}
Am I missing something here? Why is it not treating the property as List even it is a list?
In your model object you have properties with specific types, for example List<string>, List<int> or something similar. I your code however you are testing for open generic type. These types are not the same, so you do not get a match in if statement. To fix that you should use function GetGenericTypeDefinition() to get underlying open generic type:
foreach (var property in properties)
{
if (property.PropertyType.IsGenericType &&
typeof(List<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()))
{
//codes here
}
}
You could try to check if item implements IList so make the check against the "contract" rather than the concrete class :
if (typeof(IList).IsAssignableFrom(property.PropertyType)
{
}
I want to initialize all public properties of generic type.
I've written the following method :
public static void EmptyModel<T>(ref T model) where T : new()
{
foreach (PropertyInfo property in typeof(T).GetProperties())
{
Type myType = property.GetType().MakeGenericType();
property.SetValue(Activator.CreateInstance(myType));//Compile error
}
}
but it has a compile error
how can I do it?
There are three problems here:
PropertyInfo.SetValue takes two arguments, a reference to an object of to set the property on (or null for static properties)`, and the value to set it too.
property.GetType() will return PropertyInfo. To get the type of the property itself, you want to use property.PropertyType instead.
Your code doesn't handle cases when there is no parameterless constructor on the property type. You can't get too fancy here without radically changing the way you're doing things, so in my code, I'll initialize the property to null if no parameterless constructor is found.
I think what you're looking for is this:
public static T EmptyModel<T>(ref T model) where T : new()
{
foreach (PropertyInfo property in typeof(T).GetProperties())
{
Type myType = property.PropertyType;
var constructor = myType.GetConstructor(Type.EmptyTypes);
if (constructor != null)
{
// will initialize to a new copy of property type
property.SetValue(model, constructor.Invoke(null));
// or property.SetValue(model, Activator.CreateInstance(myType));
}
else
{
// will initialize to the default value of property type
property.SetValue(model, null);
}
}
}
I have been reading over old questions asked ans searching MSDN help but I cant really understand what a PropertyInfo is, specifically relating to the question of looping through an array list
c# foreach (property in object)... Is there a simple way of doing this?)
I made a simple class
public MyClass
{
public double myProperty; // etc
}
and then I add class objects to a list. I want to loop through the list, to change just a property of each object
foreach ( MyClass i in MyClassList)
{
foreach ( double myProperty in i.GetType().GetProperties() )
{
// do something
}
}
but I get an error. In the linked question (above) it says to use PropertyInfo instead of 'double. what is the PropertyInfo that should replace the 'double' of myProperry and what does it represent?
PropertyInfo simply represents the fact that a property is defined for that type; it isn't per-object - it is for the type. You don't need any instances to get a PropertyInfo.
First, however, note that myProperty is not currently a property: let's fix that first:
public MyClass
{
public double MyProperty {get;set;}
}
now we can find out about that property, either by asking about "all the properties it has", i.e.
PropertyInfo[] props = typeof(MyClass).GetProperties();
or an individual property, perhaps getting the name from configuration at runtime:
PropertyInfo prop = typeof(MyClass).GetProperty("MyProperty");
You can inspect a PropertyInfo for the name, type, attributes, etc - very useful for library code. However, in regular code the simplest option is just to use static C#:
foreach(MyClass obj in MyClassList) {
obj.MyProperty = 123.45;
}
if you need to do this via reflection, then you can use SetValue:
foreach(MyClass obj in MyClassList) {
prop.SetValue(obj, 123.45, null);
}
however, reflection is relatively slow unless you go to greater lengths. For example, another alternative for targeting the "I'll know the names at runtime" scenario would be FastMember; then you can do:
var accessor = TypeAccessor.Create(typeof(MyClass));
string propName = "MyProperty";
object value = 123.45;
foreach(MyClass obj in MyClassList) {
accessor[obj, propName] = value;
}
which will be much faster than raw reflection, while having more flexibility in terms of finding property-names at runtime.
You probably want this:
foreach (MyClass i in MyClassList)
{
foreach (var myProperty in i.GetType().GetProperty("myProperty") )
{
myProperty.SetValue(i, 1.23);
}
}
This is equivalent to:
foreach (MyClass i in MyClassList)
{
i.myProperty = 1.23;
}
GetProperties returns a collection of PropertyInfo Objects.
You then need to iterate (or search) that collection for the property you want.
See here for an example of using GetProperties()
http://rhondatipton.net/2010/02/28/using-getproperties-in-c/