GetProperty("pname") returns null - c#

I want to get value for a dynamic property of a dynamic object.
Here is my Code..
public string ReturnProperty(object ob, string prop)
{
Type type = ob.GetType();
PropertyInfo pr = type.GetProperty(prop);
//Here pr is null..Dont know whats wrong
return pr.GetValue(ob, null).ToString();
}

My guess is that either it isn't a public property, or you've got the name wrong, or it isn't a property at all (but a public field).
It's impossible to say more without knowing what the actual type is, but that should be a start.
You mention that this is a "dynamic object" but that's not really very descriptive. Bear in mind that the CLR itself doesn't know anything about the DLR - if you mean this is a type which implements IDynamicMetaObjectProvider or extends DynamicObject, then you won't be able to get at the properties with "normal" reflection like this.

In my case ob did not have pr getter setter properly.
//causes GetProperty to return null
public class MyClass{
public object pr;
}
//Works
public class MyClass{
public object pr { get; set; }
}

In my case, I had to define get and set. See post above
public string MyPropertyName { get; set; }
After this I could get the property by:
typeof(MyClassItem).GetProperty("PropertyName")

If the item you are attempting to access doesn't have getter and setter accessors, then most likely it is a field.
So your code would work as follows:
FieldInfo fieldInfo = type.GetField(fieldName);

Try the Type.GetProperty(String, BindingFlags) overload and select the right binding flags.

Example for ExpandoObject(it implements IDynamicMetaObjectProvider Jon Skeet mentioned):
public static string ReturnProperty(object ob, string prop)
{
if (ob is ExpandoObject)
{
return ((ExpandoObject)ob).Single(e => e.Key == prop).Value.ToString();
}
Type type = ob.GetType();
PropertyInfo pr = type.GetProperty(prop);
return pr.GetValue(ob, null).ToString();
}
//--
dynamic dyna = new ExpandoObject();
dyna.Name = "Element";
Console.WriteLine(ReturnProperty(dyna, "Name"));

I had the same error, the problem lies in the field names, if you have a field to read from the sql "isField" and its class has a field is named "IsField". The compiler will read case sensitive , for all reason it's a different field, for that reason you have null. Check yours casesensitive fields nomenculature.

I was trying to access a public property, but I was using BindingFlags.NonPublic instead of BindingFlags.Public.

I tried this & it worked.
public string ReturnProperty(object ob, string prop)
{
Type type = ob.GetType();
PropertyInfo pr = type.GetProperty(prop);
//Here pr is null..Dont know whats wrong
return pr.GetValue(ob, null).ToString();
}
ReturnProperty(new { abc = 10 }, "abc");
Whats wrong???

I just came across this issue when I was passing in the wrong data of a sorted grid view in an MVC project.
public HolidaysGridViewModel()
{
this.Sort = "HolidayDate"; // this was the wrong name
this.SortDir = "ASC";
}
It made me realize after reading your question that you were most likely passing in the name of a business from the database instead of the name of the database column object and therefore no were results were found which may have been the cause of your null value.

Related

Getting specific properties from an object child

Struggled to come up with a decent way to ask/title this question, but will try and illustrate it as best I can.
I am working with a data structure something like this:
public Foo
{
public Bar Bar {get;set;}
}
public Bar
{
public SubTypeA TypeA {get;set;}
public SubTypeB TypeB {get;set;}
...
}
public SubTypeA
{
public int Status {get;set;}
...
}
Note that I am unable to change the data structure for this.
There are many different types in the Bar class, which all have different properties within them, but common to all of them is the property of Status.
What I need to do, is given an object of type Foo, is record the statuses for every item in the Bar object within it. Not every SubType is going to have a value every time though, some could be null.
I can sort of manage it by using a recursive function like below to loop through all the properties. It isn't ideal though I don't think as the loop could get quite large as there could be a lot of properties on each SubType.
private void GetProperties(Type classType, object instance)
{
foreach (PropertyInfo property in classType.GetProperties())
{
object value = property.GetValue(instance, null);
if (value != null)
{
if (property.Name == "Status")
{
Record(classType, value);
}
GetProperties(property.PropertyType, value);
}
}
}
Is this about the only approach that there is for such a problem?
EDIT: Going by the answer given by Selman22, I have come up with another issue wherein I am trying to create an anonymous object based on the status and name of object.
var z = instance.GetType()
.GetProperties()
.Select(x => new
{
status = x.GetValue(instance).GetType().GetProperty("status").GetValue(x, null),
name = x.Name
})
.ToList();
This is throwing an error of Object does not match target type. when trying to retrieve the value. Is this possible in a 1 liner?
Type class contains GetProperty(string name, BindingFlags method) that you can use to retrieve specific property. Instead of looping through every property use this method.
http://msdn.microsoft.com/en-us/library/system.type.getproperty(v=vs.110).aspx
// Get Type object of MyClass.
Type myType=typeof(MyClass);
// Get the PropertyInfo by passing the property name and specifying the BindingFlags.
PropertyInfo myPropInfo = myType.GetProperty("MyProperty", BindingFlags.Public | BindingFlags.Instance);
You can get all Status properties using LINQ instead of recursion:
var barInstance = typeof(Foo).GetProperty("Bar").GetValue(fooInstance);
var statusProperties = barInstance.GetType()
.GetProperties()
.Select(x => x.GetValue(barInstance).GetType().GetProperty("Status"));

Best way to assign property value dynamically based on the property name

I have a List that I am iterating through.
Inside the List<> are Argument classes which contain two properties 'PropertyName' and 'Value'
What I need to do is iterate through the collection of Arguments and assign the Value of that Argument to the Property (with the same name as current Argument) of a different class.
Example:
Argument:
PropertyName: ClientID
Value: 1234
Members Class:
ClientID = {Argument Value here}
I hope this makes sense. I have a way of doing it, hard coding the properties of my class and matching it up with the Argument list.
Something like:
foreach(var arg in List<Argument>)
{
Members.ClientID = arg.Find(x => compareName(x, "ClientID")).Value;
//where compareName just does a simple string.Compare
}
But what would the BEST way be for something like this?
EDIT: Sorry about this guys and thanks for the replies so far. Here is what I didn't mention and might make a difference.
Each argument is a different property for the same class. I am iterating through the List and each one in there will be for the same Members class I have to populate.
I wanted to mention this because im thinking in the foreach I might have to use a switch to determine what 'PropertyName' I have for that Argument. ClientID is one of them but I believe there are 14 total properties in the Members class that need populated from the Collection.
Does that change things?
Thanks again
public object this[string propertyName]
{
get
{
Type myType = typeof(UserConfiguration);
PropertyInfo myPropInfo = myType.GetProperty(propertyName);
return myPropInfo.GetValue(this, null);
}
set
{
Type myType = typeof(UserConfiguration);
PropertyInfo myPropInfo = myType.GetProperty(propertyName);
myPropInfo.SetValue(this, value, null);
}
}
Then you can get/set properties within the class using
myClassInstance["ClientId"] = myValue;
If I understand what you're asking, perhaps something like this will work for you:
var argDict = arguments.ToDictionary(x => x.PropertyName, x => x.Value);
Members.ClientID = argDict["ClientID"];
...
If you need to do some special comparison on the keys you can provide the dictionary it's own IEqualityComparer. For example, this will make sure that the keys are treated case-insensitively:
var argDict = arguments.ToDictionary(x => x.PropertyName, x => x.Value,
StringComparer.OrdinalIgnoreCase);
This will work fine as long as the arguments list contains all the values you need. If some arguments might be missing, you'd have to do something like this:
if (argDict.ContainsKey("ClientID")) {
Members.ClientID = argDict["ClientID"];
}
Or possibly something like this:
Members.ClientID = argDict.ContainsKey("ClientID") ? argDict["ClientID"] : "DefaultValue";
I think that your basic intent is to set the value of a property on a target object based on the property name. Since you did not provide the Argument class I will assume it is defined like this:
public class Argument
{
public string PropertyName{get; set;}
public object PropertyValue{get;set;}
}
Further assume you have the class Blah defined like this:
public class Blah
{
public string AString{get; set;}
public int AnInt{get; set;}
public DirectoryInfo ADirInfo{get; set;}
}
If you wish to assign to the properties of a Blah object based on the values in List<Argument> you can do so like this:
List<Argument> arguments = new List<Argument>
{
new Argument(){PropertyName = "AString", PropertyValue = "this is a string"},
new Argument(){PropertyName = "AnInt", PropertyValue = 1729},
new Argument(){PropertyName = "ADirInfo", PropertyValue = new DirectoryInfo(#"c:\logs")}
};
Blah b = new Blah();
Type blahType = b.GetType();
foreach(Argument arg in arguments)
{
PropertyInfo prop = blahType.GetProperty(arg.PropertyName);
// If prop == null then GetProperty() couldn't find a property by that name. Either it doesn't exist, it's not public, or it's defined on a parent class
if(prop != null)
{
prop.SetValue(b, arg.PropertyValue);
}
}
This depends on the objects stored in Argument.PropertyValue having the same type as the property of Blah referred to by Argument.PropertyName (or there must be an implicit type conversion available). For example, if you alter the List<Argument> as follows:
List<Argument> arguments = new List<Argument>
{
new Argument(){PropertyName = "AString", PropertyValue = "this is a string"},
new Argument(){PropertyName = "AnInt", PropertyValue = 1729},
new Argument(){PropertyName = "ADirInfo", PropertyValue = "foo"}
};
you will now get an exception when attempting to assign to Blah.ADirInfo: Object of type 'System.String' cannot be converted to type 'System.IO.DirectoryInfo'

Set PropertyName using variable value

I want to create a property of a class, and set the name of that property using a variable value.
E.g.
string resultValue = "stack";
MyClass myclass = new MyClass();
myclass.resultValue = "overflow";
Now here in this case, stack is the property name and "overflow" is the value of the stack property.
Please tell how is it possible.
Thanks in advance.
You could use Reflection. For example:
string name = "stack";
string value = "overflow";
PropertyInfo pi = typeof(MyClass).GetProperty(name);
MyClass instance = new MyClass();
pi.SetValue(instance, value, null);
// at this stage instance.stack equals to "overflow"
This obviously assumes that MyClass has a public property stack with a public setter:
public class MyClass
{
public string stack { get; set; }
}
You should use Reflection for this
MyClass myclass = new MyClass();
Type type = typeof(MyClass);
PropertyInfo property = type.GetProperty("stack");
property.SetValue(myclass, "overflow", null);
I think that the Dynamic Source Code Generation and Compilation section on MSDN should contain the information you need.
The .NET Framework includes a mechanism called the Code Document
Object Model (CodeDOM) that enables developers of programs that emit
source code to generate source code in multiple programming languages
at run time, based on a single model that represents the code to
render.
I think that you could also get this done using Reflection.
Maybe you should take a look at DynamicObject. With this you can create properties at runtime by simply assigning a value. An example can also be found at the MSDN article.
Have at look at Mark Gravell's FastMember
It allows you to set properties in a dynamic manner.
// obj could be static or DLR
var wrapped = ObjectAccessor.Create(obj);
string propName = // something known only at runtime
FastMember Blog Post
I can't imagine why you want to generate property on your class, but consider other ways. E.g. using Dictionary:
class MyClass
{
Dictionary<string, object> _values = new Dictionary<string, object>();
public object this[string name]
{
get
{
if (!_values.ContainsKey(name))
throw new ArgumentException(name);
return _values[name];
}
set
{
if (!_values.ContainsKey(name))
{
_values.Add(name, value);
return;
}
_values[name] = value;
}
}
}
Usage:
MyClass myClass = new MyClass();
myClass["stack"] = "overflow";
Console.WriteLine(myClass["stack"]);
As far as I know, is this not possible. You can try using a dictionary.

Getting the name of a property in c#

Given this class:
public class MyClass
{
public int MyProperty {get; set;}
}
How will I be able to extract the name of MyProperty in code?
For example, I am able to get the name of the class like this
typeof(MyClass).Name
How can I do something similar for the property?
The reason for the question is that I want this particular code to be resistant against refactorizations of the names.
EDIT: With resistant I mean that I want the code at the call site to be robust in the face of changes of the propertyname. I have some stuff that is using a string representation of the property name. Sorry for the poor phrasing.
I did not include call site code in order to keep the problem clean and not wander off into other discussions on the nature of the call site code.
You do it like this, using compiler generated expression trees:
public static string GetMemberName<T, TValue>(Expression<Func<T, TValue>> memberAccess)
{
return ((MemberExpression)memberAccess.Body).Member.Name;
}
Now call the static method from code:
class MyClass
{
public int Field;
public string Property { get; set; }
}
var fieldName = GetMemberName((MyClass c) => c.Field);
var propertyName = GetMemberName((MyClass c) => c.Property);
// fieldName has string value of `Field`
// propertyName has string value of `Property`
You can now also use refactoring to rename that field without breaking this code
In C# 6 we can do it very simply
nameof(MyField);
you can get method\type\propery\field\class\namespace names in the same way
ex
nameof(MyClass);
nameof(namespacename1) // returns "namespacename1"
nameof(TestEnum.FirstValue) // returns enum's first value
MSDN Reference
Look at this post
With C# 6.0, you can use the new nameof operator.
nameof(MyClass.MyField) // returns "MyField"
nameof(MyClass) //returns "MyClass"
See nameof (C# and Visual Basic Reference) for more examples.
Using Reflection you can find all Members from MyClass with this.
MemberInfo[] members = typeof(MyClass).GetMembers();
Now you can find your desired property for each Member.
foreach ( MemberInfo memberInfo in members)
{
Console.WriteLine("Name: {0}", memberInfo.Name); // Name: MyField
Console.WriteLine("Member Type: {0}", memberInfo.MemberType); // Member Type: Property
}
If you want to find only Properties use PropertyInfo instead of MemberInfo.
Or write this
foreach ( MemberInfo memberInfo in members.Where(p => p.MemberType == MemberTypes.Property))
{
Console.WriteLine("Name: {0}", memberInfo.Name); // Name: MyField
Console.WriteLine("Member Type: {0}", memberInfo.MemberType); // Member Type: Property
}
You could use the following class which contains a method using an expression tree as an argument to determine a member name based on a lambda expression:
public class MemberHelper<T>
{
public string GetName<U>(Expression<Func<T, U>> expression)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression != null)
return memberExpression.Member.Name;
throw new InvalidOperationException("Member expression expected");
}
}
Then use it like so:
MemberHelper<MyClass> memberHelper = new MemberHelper<MyClass>();
string name = memberHelper.GetName(x => x.MyField);
If you only want to get name of an instance member, you can use shorter code:
public static string GetMemberName<TValue>(Expression<Func<TValue>> memberAccess)
{
return ((MemberExpression)memberAccess.Body).Member.Name;
}
And use it like the following inside the class:
ReflectionTools.GetMemberName(() => _someInstanceVariableOrProperty)
If you don’t want to waste your time, try the following one. I know there will be people run into the same problem.
// Soner - tested!
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(item))
{
string name = descriptor.Name; // Name
object value = descriptor.GetValue(item); // Value
var type = descriptor.PropertyType; // Type
Console.WriteLine($"{name}={value}={type}");
}
Don’t forget to add using System.ComponentModel;.

C# setting property values through reflection with attributes

I am trying to build an object through an attribute on a classes property that specifies a column in a supplied data row that is the value of the property, as below:
[StoredDataValue("guid")]
public string Guid { get; protected set; }
[StoredDataValue("PrograGuid")]
public string ProgramGuid { get; protected set; }
In a Build() method on a base object, I am getting the attribute values set on these properties as
MemberInfo info = GetType();
object[] properties = info.GetCustomAttributes(true);
However, at this point I am realising the limitation in my knowledge.
For a start, I don't appear to be getting back the correct attributes.
And how do I set these properties through reflection, now that I have the attributes? Am I doing / thinking something fundamentally incorrect?
There are a couple of separate issues here
typeof(MyClass).GetCustomAttributes(bool) (or GetType().GetCustomAttributes(bool)) returns the attributes on the class itself, not the attributes on members. You will have to invoke typeof(MyClass).GetProperties() to get a list of properties in the class, and then check each of them.
Once you got the property, I think you should use Attribute.GetCustomAttribute() instead of MemberInfo.GetGustomAttributes() since you exactly know what attribute you are looking for.
Here's a little code snippet to help you start:
PropertyInfo[] properties = typeof(MyClass).GetProperties();
foreach(PropertyInfo property in properties)
{
StoredDataValueAttribute attribute =
Attribute.GetCustomAttribute(property, typeof(StoredDataValueAttribute)) as StoredDataValueAttribute;
if (attribute != null) // This property has a StoredDataValueAttribute
{
property.SetValue(instanceOfMyClass, attribute.DataValue, null); // null means no indexes
}
}
EDIT: Don't forget that Type.GetProperties() only returns public properties by default. You will have to use Type.GetProperties(BindingFlags) to get other sorts of properties as well.

Categories

Resources