Failing to get fields of an object - c#

Simple c# console application to check how to get fields of an unknown object.
public class A
{
public int id;
public string name;
public string desc;
}
class Program
{
static void Main(string[] args)
{
A a = new A();
getProp(a);
Console.ReadKey();
}
static object getProp(object o)
{
Type type = o.GetType();
PropertyInfo[] pros = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
//Do Something
return null;
}
}
I am not getting any fields. pros has no value inside it. I have to get the field names of the object o.

The members which you're trying to fetch are not properties, but fields. Try the following:
var fields = typeof(A).GetFields();
Or:
static FieldInfo[] GetFields(object o)
{
Type type = o.GetType();
FieldInfo[] fields = type.GetFields();
return fields;
}
And in order to grab the object's fields values:
var fields = GetFields(obj);
foreach(var field in fields)
{
Console.WriteLine(field.GetValue(obj));
}
From MSDN:
Type.GetFields Method
Returns all the public fields of the current Type.

Related

Get with Reflection fields that are not generated by the compiler

Recently I was writing a method to construct a graph with the dependencies between classes using Reflection and found the following problem. My method analyzes the return type of property, generic arguments of class definition and instance fields of those classes.
For inspection of instance fields of class I use the following method.
public static IEnumerable<FieldInfo> GetFields(Type classType)
{
return classType
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
To test it, I write the following class definition:
static void Main(string[] args)
{
foreach (var fieldInfo in GetFields(typeof(A)))
Console.WriteLine(fieldInfo.Name);
Console.ReadKey();
}
class A
{
private ulong? _field1;
public byte PropertyA { get; set; }
public int PropertyB { get; set; }
public bool PropertyC { get; set; }
}
I was in shock for a few seconds, to see the result. It was when I remembered that .NET generates an instance field, Set and Get methods to emulate the properties.
When I inspected with .NET Reflector the library to see the code generated by the compiler, I find the following definition.
class A
{
private ulong? _field1;
[CompilerGenerated]
private Byte <PropertyA>k__BackingField;
[CompilerGenerated]
private Int32 <PropertyB>k__BackingField;
[CompilerGenerated]
private bool <PropertyC>k__BackingField;
}
So I modified the method to exclude the fields with CompilerGenerated attribute and his name match with some property.
public static IEnumerable<FieldInfo> GetFields(Type classType)
{
var regex = new Regex(#"^<(?<PropertyName>\w+)>\w+$");
var fieldInfoes = classType
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var fieldInfo in fieldInfoes)
{
if (fieldInfo.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
yield return fieldInfo;
else
{
var match = regex.Match(fieldInfo.Name);
if (!match.Success)
continue;
var propertyName = match.Groups[#"PropertyName"].Value;
if (classType.GetProperty(propertyName) == null)
yield return fieldInfo;
}
}
}
QUESTIONS
There is some combination of BindingFlags I'm missing for these fields?
There is another way of getting these fields because this code appears to me that is like killing a mosquito with a bazooka?
You can download the complete code here.
You need the fields that are: !field.IsDefined(typeof(CompilerGeneratedAttribute), false)
public static IEnumerable<FieldInfo> GetFields(Type classType)
{
var allFields = classType
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var definedFields = from field in allFields
where !field.IsDefined(typeof(CompilerGeneratedAttribute), false)
select field;
return definedFields;
}

Get name of static property in static class with LINQ (expression)? [duplicate]

I want to make a C# Dictionary in which the key is the string name of a static property in a class and the value is the value of the property. Given a static property in the class called MyResources.TOKEN_ONE, how can I get the at the name of the property rather than its value? I only care about the end part of the property name (e.g. "TOKEN_ONE").
I've edited this to mention that I don't want to map all property values in the Dictionary, just a small subset of everything that's in the class. So assume that I want to get the name for a single property. Given MyResources.TOKEN_ONE, I want to get back "MyResources.TOKEN_ONE" or just "TOKEN_ONE".
Here's some sample code that shows what I'm trying to do. I need the property name because I'm trying to generate a javascript variable in which I map the property name to the variable name and the property value to the variable value. For example, I want the C# Dictionary to generate lines like the one below:
var TOKEN_ONE = "One";
using System;
using System.Collections.Generic;
namespace MyConsoleApp
{
class Program
{
static void Main(string[] args)
{
Dictionary<String, String> kvp = new Dictionary<String, String>();
// How can I use the name of static property in a class as the key for the dictionary?
// For example, I'd like to do something like the following where 'PropertyNameFromReflection'
// is a mechanism that would return "MyResources.TOKEN_ONE"
kvp.Add(MyResources.TOKEN_ONE.PropertyNameFromReflection, MyResources.TOKEN_ONE);
kvp.Add(MyResources.TOKEN_TWO.PropertyNameFromReflection, MyResources.TOKEN_TWO);
Console.ReadLine();
}
}
public static class MyResources
{
public static string TOKEN_ONE
{
get { return "One"; }
}
public static string TOKEN_TWO
{
get { return "Two"; }
}
}
}
If all you want is just to be able to refer to a single, specific property in one place in the code without having to refer to it by a literal string, then you can use an expression tree. For example, the following code declares a method that turns such an expression tree into a PropertyInfo object:
public static PropertyInfo GetProperty(Expression<Func<string>> expr)
{
var member = expr.Body as MemberExpression;
if (member == null)
throw new InvalidOperationException("Expression is not a member access expression.");
var property = member.Member as PropertyInfo;
if (property == null)
throw new InvalidOperationException("Member in expression is not a property.");
return property;
}
Now you can do something like this:
public void AddJavaScriptToken(Expression<Func<string>> propertyExpression)
{
var p = GetProperty(propertyExpression);
_javaScriptTokens.Add(p.Name, (string) p.GetValue(null, null));
}
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(() => Tokens.TOKEN_ONE);
AddJavaScriptToken(() => Tokens.TOKEN_TWO);
}
Here is a function that will get you the names of all static properties in a given type.
public static IEnumerable<string> GetStaticPropertyNames(Type t) {
foreach ( var prop in t.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ) {
yield return prop.Name;
}
}
If you want to build up the map of all property names to their values you can do the following
public static Dictionary<string,object> GetStaticPropertyBag(Type t) {
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var map = new Dictionary<string,object>();
foreach ( var prop in t.GetProperties(flags) ) {
map[prop.Name] = prop.GetValue(null,null);
}
return map;
}
Now you can call it with the following
var bag = GetStaticPropertyBag(typeof(MyResources));
You can accomplish this with reflection. The easiest way to get the property names is to loop over all of them.
foreach(var propInfo in this.GetType().GetProperties()) {
var name = propInfo.Name;
var value = propInfo.GetValue(this, null);
}
See GetProperties() and GetValue() for more specifics.
Well, I'm reluctantly answering my own question because I don't think it's possible to do this for a single static property. Ultimately, I ended up hard-coding the key in the Dictionary using a cut-and-paste of the property name. Here's what I ended up with:
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(Token.FOOBAR_TITLE, "FOOBAR_TITLE");
}
And here's the rest of the code:
protected Dictionary<String, String> _javaScriptTokens = new Dictionary<String, String>();
public void AddJavaScriptToken(string tokenValue, string propertyName)
{
_javaScriptTokens.Add(propertyName, tokenValue);
}
protected override void OnPreRender(EventArgs e)
{
if (_javaScriptTokens.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<String, String> kvp in _javaScriptTokens)
{
sb.AppendLine(String.Format("var TOKEN_{0} = unescape('{1}');", kvp.Key, PUtilities.Escape(kvp.Value)));
}
ClientScript.RegisterStartupScript(this.GetType(), "PAGE_TOKENS", sb.ToString(), true);
}
base.OnPreRender(e);
}
I hate having to use cut-and-paste hard-coding to keep the property name and the key in sync...Oh well...
Other answers have already explained how you can get a list of the static properties via Reflection. You said you don’t want all of them, only a subset of them. It seems, therefore, that you need a way to distinguish the properties you want from the ones you don’t want. One way to do this is using custom attributes.
Declare a custom attribute class:
[AttributeUsage(AttributeTargets.Property)]
public class WantThisAttribute : Attribute { }
Add this custom attribute to the properties you want:
public static class MyResources
{
[WantThis]
public static string TOKEN_ONE { get { return "One"; } }
[WantThis]
public static string TOKEN_TWO { get { return "Two"; } }
public static string DontWantThis { get { return "Nope"; } }
}
Iterate over the properties to find the ones you want:
public static Dictionary<string, object> GetStaticPropertyBag(Type t)
{
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var map = new Dictionary<string, object>();
foreach (var prop in t.GetProperties(flags))
if (prop.IsDefined(typeof(WantThisAttribute), true))
map[prop.Name] = prop.GetValue(null,null);
return map;
}

Dynamically access class and its property in C#

I need to access something like strClassname.strPropertyName I will have different values for strClassname and strProperty name in program execution.
Please direct me in right way.
Sounds to me like you are trying to get (or set) the value of a property on an object at runtime. So here's the most basic way to do this:
public static object GetPropertyValue(object instance, string strPropertyName)
{
Type type = instance.GetType();
System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName);
return propertyInfo.GetValue(instance, null);
}
... and to set a value:
public static void SetPropertyValue(object instance, string strPropertyName, object newValue)
{
Type type = instance.GetType();
System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName);
propertyInfo.SetValue(instance, newValue, null);
}
If you're attempting to get the names of properties of a class, here's a function for that:
public static IEnumerable<string> GetPropertyNames(string className)
{
Type type = Type.GetType(className);
return type.GetProperties().Select(p => p.Name);
}
Say that you have 100 objects, and you want to get the value of the Name property on each of them, here's a function that will do that:
public static IEnumerable<String> GetNames(IEnumerable<Object> objects, string nameProperty = "Name")
{
foreach (var instance in objects)
{
var type = instance.GetType();
var property = type.GetProperty(nameProperty);
yield return property.GetValue(instance, null) as string;
}
}
You can use reflection:
To get names of properties for a specific type use method Type.GetProper­ties. Method returns array of PropertyInfo objects and the property names are available through PropertyInfo.Name property. If you want to get only subset of all properties (e.g. only public static ones) use BindingFlags when calling GetProperties method. You have to specify at least two flags, one from Public/NonPublic and one of Instance/Static flags. If you use GetProperties without a BindingFlags parameter, default flags are Public + NonPublic + Instance.
Following example shows how to get public static properties.
using System.Reflection; // reflection namespace
// get all public static properties of MyClass type
PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public |
BindingFlags.Static);
// sort properties by name
Array.Sort(propertyInfos,
delegate(PropertyInfo propertyInfo1, PropertyInfo propertyInfo2)
{ return propertyInfo1.Name.CompareTo(propertyInfo2.Name); });
// write property names
foreach (PropertyInfo propertyInfo in propertyInfos)
{
Console.WriteLine(propertyInfo.Name);
}
[Source]
if there's a hundred or so classes and you know you want to access a specific property on each and you know every class will be instantiated, you should definitely consider creating an interface holding the property you wish to access ex.
public interface INamed
{
Name { get; }
}
Example usage:
var namedInstances = listOfClasses.Of<INamed>().Cast<INamed>();
foreach(var instance in namedInstances)
{
var name = instance.Name;
}
On the other hand, if you're not planning to instantiate these classes, you could try the following approach instead if the 'Name' property is static or const:
public interface INamed { } //Marker interface
public static class GetNamedHelper
{
private static IEnumerable<Type> GetAssemblyTypes(IEnumerable<Assembly> assemblies)
{
if (assemblies == null) yield break;
foreach (var assembly in assemblies.Where(assembly => assembly != null))
{
IEnumerable<Type> types;
try
{
types = assembly.GetTypes().Where(t => t != null);
}
catch (ReflectionTypeLoadException rtle)
{
types = rtle.Types.Where(t => t != null);
}
foreach (var type in types)
yield return type;
}
}
private static readonly Type namedMarkerInterface = typeof (INamed);
public static IEnumerable<string> GetNames(params Assembly[] assemblies)
{
var types = GetAssemblyTypes(assemblies)
.Where(t => t.GetInterfaces().Any(intf => intf == namedMarkerInterface));
foreach (var type in types)
{
//ex. public static string Name
var prop = type.GetProperty("Name", BindingFlags.Public | BindingFlags.Static);
if (prop == null || !prop.CanRead) continue;
yield return prop.GetValue(null, null) as string;
//ex. public const string Name
var field = type.GetField("Name", BindingFlags.Public);
if (field == null || !field.IsStatic) continue;
yield return field.GetValue(null) as string;
}
}
}
Eitherway, you need to know which classes to check and for what.

How can I get the name of a C# static class property using reflection?

I want to make a C# Dictionary in which the key is the string name of a static property in a class and the value is the value of the property. Given a static property in the class called MyResources.TOKEN_ONE, how can I get the at the name of the property rather than its value? I only care about the end part of the property name (e.g. "TOKEN_ONE").
I've edited this to mention that I don't want to map all property values in the Dictionary, just a small subset of everything that's in the class. So assume that I want to get the name for a single property. Given MyResources.TOKEN_ONE, I want to get back "MyResources.TOKEN_ONE" or just "TOKEN_ONE".
Here's some sample code that shows what I'm trying to do. I need the property name because I'm trying to generate a javascript variable in which I map the property name to the variable name and the property value to the variable value. For example, I want the C# Dictionary to generate lines like the one below:
var TOKEN_ONE = "One";
using System;
using System.Collections.Generic;
namespace MyConsoleApp
{
class Program
{
static void Main(string[] args)
{
Dictionary<String, String> kvp = new Dictionary<String, String>();
// How can I use the name of static property in a class as the key for the dictionary?
// For example, I'd like to do something like the following where 'PropertyNameFromReflection'
// is a mechanism that would return "MyResources.TOKEN_ONE"
kvp.Add(MyResources.TOKEN_ONE.PropertyNameFromReflection, MyResources.TOKEN_ONE);
kvp.Add(MyResources.TOKEN_TWO.PropertyNameFromReflection, MyResources.TOKEN_TWO);
Console.ReadLine();
}
}
public static class MyResources
{
public static string TOKEN_ONE
{
get { return "One"; }
}
public static string TOKEN_TWO
{
get { return "Two"; }
}
}
}
If all you want is just to be able to refer to a single, specific property in one place in the code without having to refer to it by a literal string, then you can use an expression tree. For example, the following code declares a method that turns such an expression tree into a PropertyInfo object:
public static PropertyInfo GetProperty(Expression<Func<string>> expr)
{
var member = expr.Body as MemberExpression;
if (member == null)
throw new InvalidOperationException("Expression is not a member access expression.");
var property = member.Member as PropertyInfo;
if (property == null)
throw new InvalidOperationException("Member in expression is not a property.");
return property;
}
Now you can do something like this:
public void AddJavaScriptToken(Expression<Func<string>> propertyExpression)
{
var p = GetProperty(propertyExpression);
_javaScriptTokens.Add(p.Name, (string) p.GetValue(null, null));
}
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(() => Tokens.TOKEN_ONE);
AddJavaScriptToken(() => Tokens.TOKEN_TWO);
}
Here is a function that will get you the names of all static properties in a given type.
public static IEnumerable<string> GetStaticPropertyNames(Type t) {
foreach ( var prop in t.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ) {
yield return prop.Name;
}
}
If you want to build up the map of all property names to their values you can do the following
public static Dictionary<string,object> GetStaticPropertyBag(Type t) {
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var map = new Dictionary<string,object>();
foreach ( var prop in t.GetProperties(flags) ) {
map[prop.Name] = prop.GetValue(null,null);
}
return map;
}
Now you can call it with the following
var bag = GetStaticPropertyBag(typeof(MyResources));
You can accomplish this with reflection. The easiest way to get the property names is to loop over all of them.
foreach(var propInfo in this.GetType().GetProperties()) {
var name = propInfo.Name;
var value = propInfo.GetValue(this, null);
}
See GetProperties() and GetValue() for more specifics.
Well, I'm reluctantly answering my own question because I don't think it's possible to do this for a single static property. Ultimately, I ended up hard-coding the key in the Dictionary using a cut-and-paste of the property name. Here's what I ended up with:
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(Token.FOOBAR_TITLE, "FOOBAR_TITLE");
}
And here's the rest of the code:
protected Dictionary<String, String> _javaScriptTokens = new Dictionary<String, String>();
public void AddJavaScriptToken(string tokenValue, string propertyName)
{
_javaScriptTokens.Add(propertyName, tokenValue);
}
protected override void OnPreRender(EventArgs e)
{
if (_javaScriptTokens.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<String, String> kvp in _javaScriptTokens)
{
sb.AppendLine(String.Format("var TOKEN_{0} = unescape('{1}');", kvp.Key, PUtilities.Escape(kvp.Value)));
}
ClientScript.RegisterStartupScript(this.GetType(), "PAGE_TOKENS", sb.ToString(), true);
}
base.OnPreRender(e);
}
I hate having to use cut-and-paste hard-coding to keep the property name and the key in sync...Oh well...
Other answers have already explained how you can get a list of the static properties via Reflection. You said you don’t want all of them, only a subset of them. It seems, therefore, that you need a way to distinguish the properties you want from the ones you don’t want. One way to do this is using custom attributes.
Declare a custom attribute class:
[AttributeUsage(AttributeTargets.Property)]
public class WantThisAttribute : Attribute { }
Add this custom attribute to the properties you want:
public static class MyResources
{
[WantThis]
public static string TOKEN_ONE { get { return "One"; } }
[WantThis]
public static string TOKEN_TWO { get { return "Two"; } }
public static string DontWantThis { get { return "Nope"; } }
}
Iterate over the properties to find the ones you want:
public static Dictionary<string, object> GetStaticPropertyBag(Type t)
{
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var map = new Dictionary<string, object>();
foreach (var prop in t.GetProperties(flags))
if (prop.IsDefined(typeof(WantThisAttribute), true))
map[prop.Name] = prop.GetValue(null,null);
return map;
}

How do I get the FieldInfo of an array field?

I'm trying to get the field info of an array value from within a struct. So far I have the following, but I dont see how to get the infomration I want.
[StructLayout(LayoutKind.Sequential)]
public struct Test
{
public byte Byte1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
public Test2[] Test1;
}
BindingFlags struct_field_flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
FieldInfo[] all_struct_fields = typeof(Test).GetFields(struct_field_flags);
foreach (FieldInfo struct_field in all_struct_fields)
{
if(struct_field.FieldType.IsArray)
{
// Get FieldInfo for each value in the Test1 array within Test structure
}
}
So if I did:
Type array_type = struct_field.FieldType.GetElementType();
This would return Test2 type, but I dont want the type of the array, I want the FieldInfo or Fields of that structure so I can set values from within it.
Sorry for the initial wrong answer. I was too lazy to create my own Test2 type so I used a string instead. Here's the right answer (hopefully):
I did what you want to do with the following code:
class Program
{
static void Main(string[] args)
{
object sampleObject = GetSampleObject();
FieldInfo[] testStructFields = typeof(Test).GetFields();
foreach (FieldInfo testStructField in testStructFields)
{
if (testStructField.FieldType.IsArray)
{
// We can cast to ILIst because arrays implement it and we verfied that it is an array in the if statement
System.Collections.IList sampleObject_test1 = (System.Collections.IList)testStructField.GetValue(sampleObject);
// We can now get the first element of the array of Test2s:
object sampleObject_test1_Element0 = sampleObject_test1[0];
// I hope this the FieldInfo that you want to get:
FieldInfo myValueFieldInfo = sampleObject_test1_Element0.GetType().GetField("MyValue");
// Now it is possible to read and write values
object sampleObject_test1_Element0_MyValue = myValueFieldInfo.GetValue(sampleObject_test1_Element0);
Console.WriteLine(sampleObject_test1_Element0_MyValue); // prints 99
myValueFieldInfo.SetValue(sampleObject_test1_Element0, 55);
sampleObject_test1_Element0_MyValue = myValueFieldInfo.GetValue(sampleObject_test1_Element0);
Console.WriteLine(sampleObject_test1_Element0_MyValue); // prints 55
}
}
}
static object GetSampleObject()
{
Test sampleTest = new Test();
sampleTest.Test1 = new Test2[5];
sampleTest.Test1[0] = new Test2() { MyValue = 99 };
object sampleObject = sampleTest;
return sampleObject;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Test2
{
public int MyValue;
}
[StructLayout(LayoutKind.Sequential)]
public struct Test
{
public byte Byte1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Test2[] Test1;
}
This is the most important line:
FieldInfo myValueFieldInfo = sampleObject_test1_Element0.GetType().GetField("MyValue");
It should give you the FieldInfo that you are talking about.
What exactly are you after? There is no FieldInfo for the items in the array... you can iterate the values by getting the array (as Array) and iterating it... just use:
Array arr = (Array)field.GetValue(obj);
The problem with #weiqure's technique is that it only works if the array already has at least one element in it. Here is a way to find the array's element type, whether it contains elements or not:
bool GetArrayElementType(FieldInfo field, out Type elementType)
{
if (field.FieldType.IsArray && field.FieldType.FullName.EndsWith("[]"))
{
string fullName = field.FieldType.FullName.Substring(0, field.FieldType.FullName.Length - 2);
elementType = Type.GetType(string.Format("{0},{1}", fullName, field.FieldType.Assembly.GetName().Name));
return true;
}
elementType = null;
return false;
}
And here is how you would use that function:
void Test(object targetObject, string fieldName)
{
FieldInfo field = targetObject.GetType().GetField(fieldName);
Type elementType;
bool success = GetArrayElementType(field, out elementType);
}

Categories

Resources