Many examples such as
Set object property using reflection
Instantiate an object without reflection and then use it with reflection.
But how can the same thing be achieved with reflection to get the initial object?
My code so far is this
var currentMethod = MethodBase.GetCurrentMethod();
string currentNamespace = currentMethod.DeclaringType.Namespace;
string currentType = this.GetType().Name;
var basetype = this.GetType().Assembly.GetType(currentNamespace + "." + currentType);
PropertyInfo propertyInfo = basetype.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
PropertyInfo propertyToSet = basetype.GetProperty(OutputVariableName, BindingFlags.Public | BindingFlags.Instance);
var val = propertyInfo.GetValue(propertyToSet, null);
propertyToSet.SetValue(propertyInfo, Convert.ChangeType(prefix + suffix, propertyToSet.PropertyType), null);
This gives the error Object does not match the target type
I've also tried
propertyInfo.SetValue(propertyToSet, Convert.ChangeType(prefix + suffix, propertyToSet.PropertyType), null);
Which gives the error Property set method not found.
The properties look like this:
public static currentType Instance
{
get { return instance; }
}
public string NewTextName
{
get { return _NewTextName; }
set { _NewTextName = value; }
}
The intellisense for val shows all the properties and their current values, I'm expecting it to show just the property that has the name propertyToSet
The purpose of this code is to set a string property on an instance of an object. The static property returns the instance and the goal is to set the value of NewTextName, which is a non-static property.
Related
I'm trying to mod Planetbase and I have to access protected static List<Character> mCharacters = new List<Character>(); inside public abstract class Character in Planetbase namespace. Here is my code:
FieldInfo characters = typeof(Character).GetField("mCharacters", BindingFlags.NonPublic | BindingFlags.Instance);
carriedResources = Character.characters.Where(x => x.getLoadedResource() != null)
.ToDictionary(y => y, x => x.getLoadedResource()); // Get all carried resources across all characters
However I'm getting the "Character does not contain the definition for characters" error despite writing a method to access it. No idea what I'm doing wrong.
The BindingFlags you are using are not correct. What you need is BindingFlags.NonPublic | BindingFlags.Static. You can find out more about this enumeration here.
These are some of the most used binding flags when one would search for any type member (field, property, method, etc.):
BindingFlags.Public specifies that public members are to be included in the search.
BindingFlags.NonPublic specifies that non-public members are to be included in the search.
BindingFlags.Instance specifies that instance members are to be included in the search.
BindingFlags.Static specifies that static members are to be included in the search.
Update:
I just noticed that you are not accessing the field information appropriately. After you have the field info, you can access the underlying value like this:
FieldInfo field = typeof(Character).GetField("mCharacters", BindingFlags.NonPublic | BindingFlags.Instance);
var value = field.GetValue(__character_instance__);
The retrieved value will be of type object so you have to safely convert it to the appropriate type.
So if I have this class:
public class Person
{
private readonly string _name;
public Person(string name)
{
this._name = name;
}
}
I can access the field data like this:
var person = new Person("Tony Troeff");
var field = typeof(Person).GetField("_name", BindingFlags.NonPublic | BindingFlags.Instance);
var fieldValue = field.GetValue(person) as string;
public class Foo
{
private Bar FooBar {get;set;}
private class Bar
{
private string Str {get;set;}
public Bar() {Str = "some value";}
}
}
If I've got something like the above and I have a reference to Foo, how can I use reflection to get the value Str out Foo's FooBar? I know there's no actual reason to ever do something like this (or very very few ways), but I figure there has to be a way to do it and I can't figure out how to accomplish it.
edited because I asked the wrong question in the body that differs from the correct question in the title
You can use the GetProperty method along with the NonPublic and Instance binding flags.
Assuming you have an instance of Foo, f:
PropertyInfo prop =
typeof(Foo).GetProperty("FooBar", BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo getter = prop.GetGetMethod(nonPublic: true);
object bar = getter.Invoke(f, null);
Update:
If you want to access the Str property, just do the same thing on the bar object that's retrieved:
PropertyInfo strProperty =
bar.GetType().GetProperty("Str", BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo strGetter = strProperty.GetGetMethod(nonPublic: true);
string val = (string)strGetter.Invoke(bar, null);
There is a way to slightly simplify Andrew's answer.
Replace the calls to GetGetMethod() + Invoke() with a single call to GetValue() :
PropertyInfo barGetter =
typeof(Foo).GetProperty("FooBar", BindingFlags.NonPublic | BindingFlags.Instance);
object bar = barGetter.GetValue(f);
PropertyInfo strGetter =
bar.GetType().GetProperty("Str", BindingFlags.NonPublic | BindingFlags.Instance);
string val = (string)strGetter.GetValue(bar);
I did some testing, and I didn't find a difference, then I found this answer, which says that GetValue() calls GetGetMethod() with error checking, so there is no practical difference (unless you worry about performance, but when using Reflection I guess that you won't).
I'd like to reset the properties of a class back to their default values within a method of the class. My class is instantiated once (is actually a ViewModel in an MVVM framework) and I don't want to destroy and recreate the entire ViewModel, just clear many of the properties. The below code is what I have. The only thing I am missing is how to get the first parameter of the SetValue method - I know it is an instance of the property I am setting, but I cannot seem to figure out how to access that. I get error: "Object does not match target type".
public class myViewModel
{
...
...
public void ClearFields()
{
Type type = typeof(myViewModel);
PropertyInfo[] pi = type.GetProperties();
foreach (var pinfo in pi)
{
object[] attributes = pinfo.GetCustomAttributes(typeof(DefaultValueAttribute), false);
if (attributes.Length > 0)
{
DefaultValueAttribute def = attributes[0] as DefaultValueAttribute;
pinfo.SetValue(?, def.Value, null);
}
}
}
...
...
}
You should pass an instance of myViewModel, in your case use this to reference the current instance:
public class myViewModel
{
...
...
public void ClearFields()
{
Type type = typeof(myViewModel);
PropertyInfo[] pi = type.GetProperties();
foreach (var pinfo in pi)
{
object[] attributes = pinfo.GetCustomAttributes(typeof(DefaultValueAttribute), false);
if (attributes.Length > 0)
{
DefaultValueAttribute def = attributes[0] as DefaultValueAttribute;
pinfo.SetValue(this, def.Value, null);
}
}
}
...
...
}
You should put this as a first parameter. See MSDN for reference:
objType: System.Object
The object whose property value will be set.
This is what I've done so far:
var fields = typeof (Settings.Lookup).GetFields();
Console.WriteLine(fields[0].GetValue(Settings.Lookup));
// Compile error, Class Name is not valid at this point
And this is my static class:
public static class Settings
{
public static class Lookup
{
public static string F1 ="abc";
}
}
You need to pass null to GetValue, since this field doesn't belong to any instance:
fields[0].GetValue(null)
You need to use Type.GetField(System.Reflection.BindingFlags) overload:
http://msdn.microsoft.com/en-us/library/4ek9c21e.aspx
For example:
FieldInfo field = typeof(Settings.Lookup).GetField("Lookup", BindingFlags.Public | BindingFlags.Static);
Settings.Lookup lookup = (Settings.Lookup)field.GetValue(null);
The signature of FieldInfo.GetValue is
public abstract Object GetValue(
Object obj
)
where obj is the object instance you want to retrieve the value from or null if it's a static class. So this should do:
var props = typeof (Settings.Lookup).GetFields();
Console.WriteLine(props[0].GetValue(null));
Try this
FieldInfo fieldInfo = typeof(Settings.Lookup).GetFields(BindingFlags.Static | BindingFlags.Public)[0];
object value = fieldInfo.GetValue(null); // value = "abc"
I have a class with a property Value like this:
public class MyClass {
public property var Value { get; set; }
....
}
I want to use MethodInfo.Invoke() to set property value. Here are some codes:
object o;
// use CodeDom to get instance of a dynamically built MyClass to o, codes omitted
Type type = o.GetType();
MethodInfo mi = type.GetProperty("Value");
mi.Invoke(o, new object[] {23}); // Set Value to 23?
I cannot access to my work VS right now. My question is how to set Value with a integer value such as 23?
You can use the PropertyInfo.SetValue method.
object o;
//...
Type type = o.GetType();
PropertyInfo pi = type.GetProperty("Value");
pi.SetValue(o, 23, null);
If you are using .NET Framework 4.6 and 4.5, you can also use PropertyInfo.SetMethod Property :
object o;
//...
Type type = o.GetType();
PropertyInfo pi = type.GetProperty("Value");
pi.SetMethod.Invoke(o, new object[] {23});