If I declare the following in my class:
private int? MyID = null;
And then attempt to access it via reflection, it won't be able to find it. What I mean by that is, the below will set gProp to null:
gType = refObj.GetType();
gProp = gType.GetProperty(PropertyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
However, it will work fine if I instead declare it as:
private int? MyID { get; set; }
This isn't at all surprising to me as I already knew this to be the case. However, I wanted to confirm; is there anyway to make the first declaration work with reflection, or do I have provide a Getter/Setter in order for reflection to work?
Thanks!
It is a field, not a property, so it won't be returned by GetProperty. You need to use GetField method.
You need the GetField method (instead of GetProperty) for Fields.
Type.GetFields Method
Searches for the specified field, using the specified binding constraints.
Sample
// your instance
MyObject instance = new MyObject();
// get type information
Type myType = typeof(MyObject);
// get field information
FieldInfo fieldInfo = myType.GetField("MyID");
// set some value
fieldInfo.SetValue(instance, 123);
// get field value
var value = fieldInfo.GetValue(instance);
// value is 123
More Information
MSDN - Type.GetField Method (String, BindingFlags)
MSDN - SetField Method (String, BindingFlags, Object)
There is a difference between
private int? MyID = null;
and
private int? MyID { get; set; }
The first is a field, and the second is a property.
You should use the Type.GetField() method when trying to find a field via reflection.
You should create a property for accessing the variables in the class. So you manually create a property like
private int? MyID { get { return _myID;} }
The below code works, since it is Auto property in c#
private int? MyID { get; set; }
Refer http://msdn.microsoft.com/en-us/library/bb384054.aspx
My logic states the first is a simple variable, the second is a property, because it has the get/set, so for "GetProperty" to work, it needs to be a property. If you wanted a variable, you need the GetField
Related
I have a class that looks something like this:
public class MyClass {
public string id { get; set; }
public string Id { get; set; }
public string SomethingMore {get; set;}
}
I don't control the class. So I have to live with the fact that both id (lowercase i) and Id (uppercase I) exist. Like it or not, I cannot change this, hence this answer answers my why, but it does not answer my how-to question.
In my Expression tree I have:
var newExpression = Expression.New(typeof(MyClass).GetConstructor(Type.EmptyTypes))
var propertyExpression = Expression.Property(newExpression, "Id");
The second line throws an Ambiguous Match Exception, because Expression.Property(..) is case insensitive - e.g. Expression.Property(newExpression, "SomethingMore") does not throw an exception.
What sort of work-around options do I have?
The next step in the code is:
Expression.Assign(propertyExpression, Expression.Constant("someNewValue", typeof(string));
I don't need to assign value to the id property and I know the meaning of id, which is special. I do however need to be able to assign a value to the Id property.
I guess I could create a derived version of my MyClass, that doesn't include the id property, but I need to do this at run-time. If this is the solution, how can it be done? Or, maybe there's a much better solution?
I don't control the MyClass. I only know that a developer would be inclined to define both idand Id in their class.
There are overloads for Expression.Property that allow a more explicit means of accessing the desired property.
Get the property info explicitly using reflection and use that.
var type = typeof(MyClass);
var newExpression = Expression.New(type.GetConstructor(Type.EmptyTypes));
PropertyInfo property = type.GetProperty("Id");
var propertyExpression = Expression.Property(newExpression, property);
I am working with C# reflection here:
I have a FieldInfo of a property and I would like to get the instance of the class it belong (so I can reach the content of another property):
for exemple take this class:
class MyClass
{
public int A { get; set; }
public int B { get; set; }
}
in some part of the code I have
void Function(FieldInfo fieldInfoOfA)
{
// here I need to find the value of B
}
Is this possible ?
Is this possible ?
No. Reflection is about discovery of the metadata of a type. A FieldInfo does not contain any information about a particular instance of that type. This is why you can get a FieldInfo without even creating an instance of the type at all:
typeof(MyClass).GetField(...)
Given the snippet above, you can see that a FieldInfo can be obtained without any dependence on a particular instance.
FieldInfo provides access to the metadata for a field within a class, it is independent of a specified instance.
If you have an instance of MyClass you can do this:
object Function(MyClass obj, FieldInfo fieldInfoOfA)
{
var declaringType = fieldInfoOfA.DeclaringType;
var fieldInfoOfB = declaringType.GetField("B");
return fieldInfoOfB.GetValue(obj);
}
here a solution is given to get value of a property of a class by supplying its name . now I wonder how I can do the same in this condition :
I have a class MyClass . this class ha a property of type Foo named foo . the Foo has a property of type Bar named bar . and bar has a string property named value .
properties are not static .
I want to be able to get value of foo.bar.value by passing the string "foo.bar.value" as propertyName . in other word I want to pass the property path to get its value .
is it possible ?
You can do this with a recursive method. Each call takes the value with the first word in path and call the method again with the rest of the part.
public object GetPropertyValue(object o, string path)
{
var propertyNames = path.Split('.');
var value = o.GetType().GetProperty(propertyNames[0]).GetValue(o, null);
if (propertyNames.Length == 1 || value == null)
return value;
else
{
return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
}
This assumes that the properties are named like the classes. i.e. that the property of Type Foo is also named Foo. Without this assumption, the question is lacking some crucial information.
You can use the string.Split method to separate the string foo.bar.value at the dots. You will then have an array with one element per property name.
Iterate over that array and use PropertyInfo.GetValue to retrieve the value of the properties. The value returned in one operation is the instance passed to GetValue in the following iteration.
string props = "foo.bar.value";
object currentObject = // your MyClass instance
string[] propertyChain = props.Split('.');
foreach (string propertyName in propertyChain) {
if (propertyName == "") {
break;
}
PropertyInfo prop = currentObject.GetType().GetProperty(propertyName);
currentObject = prop.GetValue(currentObject);
if (currentObject == null) {
// somehow handle the situation that one of the properties is null
}
}
Update: I have added a safeguard to ensure this will work even if props is empty. In that case, currentObject will remain a reference to the original MyClass instance.
Assuming FOO is static, you can get the class from a string like this:
C# Reflection: How to get class reference from string?
...and then use the rest of the post you've linked to to get the property and value from there:
Get property Value by its stringy name
If FOO isn't static, you'll need to use reflection on the instance (which would negate the requirement to pass in the name of the class as a string, since you can get the class from the instance with GetType()) - remembering that Bar won't have a value in the class unless it is static.
As You pointing to answer of the question here , You need to make use of Reglection to achieve same thing.
With help of reflection you can read value of property.
something like this,
// dynamically load assembly from file Test.dll
Assembly testAssembly = Assembly.LoadFile(#"c:\Test.dll");
// get type of class Calculator from just loaded assembly
Type calcType = testAssembly.GetType("Test.Calculator");
// create instance of class Calculator
object calcInstance = Activator.CreateInstance(calcType);
// get info about property: public double Number
PropertyInfo numberPropertyInfo = calcType.GetProperty("Number");
// get value of property: public double Number
double value = (double)numberPropertyInfo.GetValue(calcInstance, null);
you need a put the code in one function and than split string as per you requirement
public object getvalue(string propname)
{
//above code with return type object
}
String[] array = string.Split("foo.bar.value");
//call above method to get value of property..
Read for detail : http://www.csharp-examples.net/reflection-examples/
I wrote a custom serializer that works by setting object properties by reflection. Serializable classes are tagged with serializable attribute and all serializable properties are also tagged. For example, the following class is serializable:
[Serializable]
public class Foo
{
[SerializableProperty]
public string SomethingSerializable {get; set;}
public string SometthingNotSerializable {get; set;}
}
When the serializer is asked to deserialize SomethingSerializable, it gets the set method of the property and uses it to set it by doing something like this:
PropertyInfo propertyInfo; //the property info of the property to set
//...//
if (propertyInfo.CanWrite && propertyInfo.GetSetMethod() != null)
{
propertyInfo.GetSetMethod().Invoke(obj, new object[]{val});
}
This works fine, however, how can I make the property setter accessible only to the serializer? If the setter is private:
public string SomethingSerializable {get; private set;}
then the call to propertyInfo.GetSetMethod() returns null in the serializer. Is there any way to access the private setter or any other way to ensure that only the serializer can access the setter? The serializer is not guaranteed to be in the same assembly.
As you already figured out, one way to access a non-public setter is as follows:
PropertyInfo property = typeof(Type).GetProperty("Property");
property.DeclaringType.GetProperty("Property");
property.GetSetMethod(true).Invoke(obj, new object[] { value });
There is another way, though:
PropertyInfo property = typeof(Type).GetProperty("Property");
// if Property is defined by a base class of Type, SetValue throws
property = property.DeclaringType.GetProperty("Property");
property.SetValue(obj, value, BindingFlags.NonPublic | BindingFlags.Instance, null, null, null); // If the setter might be public, add the BindingFlags.Public flag.
Coming here from a search engine?
This question is specifically about accessing a non-public setter in a public property.
If both the property and setter are public, only the first example will work for you. To get the second example to work, you will need to add the BindingFlags.Public flag.
If the property is declared in a parent type and not visible to the type on which you're calling GetProperty, you won't be able to access it. You'll need to call GetProperty on a type to which the property is visible. (This doesn't affect private setters as long as the property itself is visible.)
If there are multiple declarations for the same property in the inheritance chain (via the new keyword), these examples will target the property that is immediately visible to the type on which GetProperty is called. For example, if class A declares Property using public int Property, and class B re-declares Property via public new int Property, typeof(B).GetProperty("Property") will return the property declared in B, while typeof(A).GetProperty("Property") will return the property declared in A.
Is there a way to obtain the object behind a property by reflection?
I am trying to manage a dynamic setting of a property.
Example:
class Animal
{
public string Name {get;set;}
public string Family {get;set;}
}
class Zoo
{
public Animal Lion {get;set;}
public Animal Panda {get;set;}
}
class Test
{
public void SetLionNameWithReflection()
{
Zoo londonZoo = new Zoo();
Type zooType = typeof(Zoo);
PropertyInfo lionProperty = zooType.GetProperty("Lion");
// Now what to write here so that I can manage to set Lion's name to Kaspar?
// (to manage this by reflection Lion.Name = "Kaspar");
}
}
What lines should I add more at the commented part above?
Thanks!
I don't think you actually need to know the object behind a property. Use the SetValue method to set its value to "Kaspar":
EDIT - as per dlev's comment, this is how it should look like:
Lion kaspar = new Lion { Name="Kaspar" };
zooType.SetValue(londonZoo, kaspar, null);
A property doesn't necessarily have an object "behind" it.
It's defined by 2 functions, get and set, that can do whatever you want, and not necessarily return an object's value at all.
What you used is just a syntactic sugar to make it easier to make a property to wrap a member.
No you can't use reflection to definitively get the object behind an arbitrary property. Largely because it's not guaranteed that every property is bound to an object. It could just as easily be a calculated value.
public class Student {
public string m_firstName;
public string m_lastName;
public string FullName {
get { return String.Format("{0} {1}", m_firstName, m_lastName); }
}
}
In this case the property FullName produces a calculated value and has no single backing object.
The case you're listing though is for auto-properties. There is likely a way to dig through the fields and use a form of name matching to get the one backing a given auto-property. However such a solution would be fragile to versioning and certainly not recomended.
Can you add an overloaded constructor to your animal object, which will allow you to pass in the animal name, like this?:
londonZoo.GetProperty("Lion").SetValue(londonZoo, new Lion("Kaspar"), null);
First you need to create the lion:
var lion = Activator.CreateInstance(lionProperty.PropertyType);
Then you need to set the Lion property of the zoo:
lionProperty.SetValue(londonZoo, lion, null);
Then you can get the Name property of the lion:
PropertyInfo property = lion.GetType().GetProperty("Name",
BindingFlags.Public | BindingFlags.Instance);
Then you can set its name:
if (property != null && property.CanWrite)
{
property.SetValue(lion, "Kaspar", null);
}