Get with Reflection fields that are not generated by the compiler - c#

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;
}

Related

How to get static properties from base type via reflection

I try to get static properties from a base type via reflection. There are many questions regarding this topic on this side, but they all focus on getting non static properties of a base type or static properties from the target type.
public class A
{
public static string STATIC_BaseProp => "STATIC_BaseProp"; //<-- I want this
public string BaseProp => "BaseProp";
}
public class B : A
{
public static string STATIC_Prop => "STATIC_Prop";
public string Prop => "PROP";
}
static void Main(string[] args)
{
var type = typeof(B);
foreach (var propertyInfo in type.GetProperties())
{
Console.log(propertyInfo);
}
}
Output:
System.String STATIC_Prop
System.String Prop
System.String BaseProp
This seems to only adress the static properties of the target type and the non static properties of the target type and the base type. But I want only the static property of the base type (STATIC_BaseProp)
Does anyone know how to do this?
To get only the static properties of the base type I would suggest to access the Type.BaseType property (like described in this answer) and use only Public | Static Bindingflags:
static void Main(string[] args)
{
var type = typeof(B);
foreach (var propertyInfo in type.BaseType.GetProperties( BindingFlags.Public | BindingFlags.Static ))
{
Console.WriteLine(propertyInfo);
}
Console.ReadKey();
}
disclaimer: this works only for one level of the inheritance hierarchy. You would need to dive through the basetypes if you want deeper insights.
Output:
System.String STATIC_BaseProp
If you want all static properties throughout the entire inheritance hierarchy you can use this combination of BindingFalgs:
type.GetProperties( BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
Here is an example to demostrate that it works also if you add a parent class on top of A
public class ParentOfA
{
public static string STATIC_ParentBaseProp => "STATIC_ParentBaseProp"; //<-- I want this
public string ParentBaseProp => "BaseProp";
}
public class A : ParentOfA
{
public static string STATIC_BaseProp => "STATIC_BaseProp"; //<-- I want this
public string BaseProp => "BaseProp";
}
public class B : A
{
public static string STATIC_Prop => "STATIC_Prop";
public string Prop => "PROP";
}
static void Main(string[] args)
{
var type = typeof(B);
foreach (var propertyInfo in type.GetProperties(
BindingFlags.Public |
BindingFlags.Static |
BindingFlags.FlattenHierarchy))
{
Console.WriteLine(propertyInfo);
}
Console.ReadKey();
}
Output:
System.String STATIC_Prop
System.String STATIC_BaseProp
System.String STATIC_ParentBaseProp

Check fields attributes using reflection

I'm trying to find a fields in a class has a Obsolete attribute ,
What I have done is , but even thought the type has an obselete attribute its not found during iteration :
public bool Check(Type type)
{
FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var field in fields)
{
if (field.GetCustomAttribute(typeof(ObsoleteAttribute), false) != null)
{
return true
}
}
}
EDIT :
class MyWorkflow: : WorkflowActivity
{
[Obsolete("obselset")]
public string ConnectionString { get; set; }
}
and using it like this , Check(typeof(MyWorkflow))
Problem is that ConnectionString is nor Field and nor NonPublic.
You should correct BindingFlags and also, use GetProperties method to search for properties.
Try the following
public static bool Check(Type type)
{
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
return props.Any(p => p.GetCustomAttribute(typeof(ObsoleteAttribute), false) != null);
}

Failing to get fields of an object

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.

List methods and invoke them at runtime

Here's the situation :
I want to create a test application which would be able to retrieve all the class and methods within a dll and allow me to call them at runtime.
What I have is something like this :
Let's say I have those classes :
public static class FirstManagerSingleton
{
public static SecondManager Instance
{
return mInstance; // which is a SecondManager private static object
}
}
public class SecondManager
{
public Service1 service1 {get; private set;}
public Service2 service2 {get; private set;}
...
}
public class Service1
{
public bool Method1()
{
return true;
}
public int Method2()
{
return 1;
}
...
}
public class Service2
{
public bool Method1()
{
return false;
}
public int Method2(int aNumber)
{
return aNumber - 1;
}
...
}
I want to be able to select each "Service" Class, call any method and show its result.
Is it possible to do this using reflection ? If it wasn't of the multiple layers (The 2 managers class) I wouldn't struggle that much. The fact is I need to access the service class through a call which look like this :
FirstManagerSingleton.Instance.Service1.Method1;
So far, I've been able to load the assembly and retrieve almost every methods and print them.
Assembly assembly = Assembly.LoadFrom("assemblyName");
// through each type in the assembly
foreach (Type type in assembly.GetTypes())
{
// Pick up a class
if (type.IsClass == true)
{
MethodInfo[] methodInfo;
Console.WriteLine("Found Class : {0}", type.FullName);
Type inter = type.GetInterface("I" + type.Name, true);
if (inter != null)
{
methodInfo = inter.GetMethods();
foreach (MethodInfo aMethod in test2)
{
Console.WriteLine("\t\tMethods : " + aMethod);
}
}
}
}
From there, I don't really know what to do next to invoke the methods.
By the way, those methods could take some parameters and have some return types.
I'm using the interface to retrieve the methods in order to filter from the methods inherited from another interface.
I hope I was clear enough. Sorry I can't post the real code sample, but I guess it's enough to illustrate the concept.
You should get the classes from the assemblies, then recursively get the property values and execute the methods. Here is some simple code that you should tailor according to your needs:
public void ExecuteAssembly(string anAssemblyName)
{
Assembly assembly = Assembly.LoadFrom(anAssemblyName);
foreach (Type type in assembly.GetTypes())
{
if (type.IsClass)
{
TypeAttributes atts = type.Attributes;
if ((atts & TypeAttributes.Sealed) != 0) // identify the static classes
ExecuteEverything(type);
}
}
}
private void ExecuteEverything(Type type)
{
// get only the public STATIC properties and methods declared in the type (i.e. not inherited)
PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
MethodInfo[] meths = type.GetMethods(BindingFlags.Public | BindingFlags.Static
| BindingFlags.DeclaredOnly);
// execute the methods which aren't property accessors (identified by IsSpecialMethod = true)
foreach (MethodInfo aMeth in meths)
if (!aMeth.IsSpecialName)
Execute(aMeth, type);
// for each property get the value and recursively execute everything
foreach (PropertyInfo aProp in props)
{
object aValue = aProp.GetValue(type, null);
if (aValue != null)
RecursivelyExecuteEverything(aValue);
}
}
private void RecursivelyExecuteEverything(object aValue)
{
Type type = aValue.GetType();
// get only the public INSTANCE properties and methods declared in the type (i.e. not inherited)
PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
MethodInfo[] meths = type.GetMethods(BindingFlags.Public | BindingFlags.Instance
| BindingFlags.DeclaredOnly);
// execute the methods which aren't property accessors (identified by IsSpecialMethod = true)
foreach (MethodInfo aMeth in meths)
if (!aMeth.IsSpecialName)
Execute(aMeth, aValue);
// for each property get the value and recursively execute everything
foreach (PropertyInfo aProp in props)
{
object newValue = aProp.GetValue(aValue, null);
if (newValue != null)
RecursivelyExecuteEverything(newValue);
}
}
private void Execute(MethodInfo aMeth, object anObj)
{
// be careful that here you should take care of the parameters.
// this version doesn't work for Method2 in Service2, since it
// requires an int as parameter
aMeth.Invoke(anObj, null);
}

Reflecting a private field from a base class

Here is the structure:
MyClass : SuperClass2
SuperClass2 : SuperClass1
superClass2 is in Product.Web and SuperClass1 is in the .NET System.Web assembly
I'm trying to force a value into a private bool field on SuperClass1. But not matter what I try I cannot get the fields to come back from reflection.
I'm using the following code with different BindingFlag combinations but nothing has worked so far. SuperClass1 is an abstract class.
((SuperClass1)this).GetType().GetFields(System.Reflection.BindingFlags.NonPublic);
Notes:
When I use GetProperties() I get back a nice big list but when I specify any bindingflags I get nothing even though there are matching properties. Whats the deal?
Also, the field is not marked internal
Obvisouly I would be using GetField(string name, BindingFlags) but I can't even get GetFlags() to work.
Update: I've tried adding BindingFlags.Instance as suggested but it doesn't work (as expected anyway). I get back 2 fields that are coming from the class SuperClass1 inherits from. Returns null when used with GetField(string name, Flags)
Here is the code for the base class I'm trying to get the field for
public abstract class BaseValidator : Label, IValidator
{
private bool propertiesChecked;
...
}
You can manually go up in the inheritance chain to get the base fields:
Given these classes:
class SuperClass1
{
private int myField;
}
class SuperClass2 : SuperClass1
{
}
class MyClass : SuperClass2
{
}
This should work:
var myObj = new MyClass();
var myField = typeof(MyClass).BaseType
.BaseType
.GetField("myField", BindingFlags.Instance | BindingFlags.NonPublic);
There's a more generic solution in this SO answer: Not getting fields from GetType().GetFields with BindingFlag.Default
In a similar vein to BrokenGlass's solution, you could do this to make it a bit more generic:
class Base { private int _baseField; }
class Derived : Base { }
class Mine : Derived { }
And then:
Type t = typeof(Mine);
FieldInfo fi = null;
while (t != null)
{
fi = t.GetField("_baseField", BindingFlags.Instance | BindingFlags.NonPublic);
if (fi != null) break;
t = t.BaseType;
}
if (fi == null)
{
throw new Exception("Field '_baseField' not found in type hierarchy.");
}
As a utility method:
public static void SetField(object target, string fieldName, object value)
{
if (target == null)
{
throw new ArgumentNullException("target", "The assignment target cannot be null.");
}
if (string.IsNullOrEmpty(fieldName))
{
throw new ArgumentException("fieldName", "The field name cannot be null or empty.");
}
Type t = target.GetType();
FieldInfo fi = null;
while (t != null)
{
fi = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (fi != null) break;
t = t.BaseType;
}
if (fi == null)
{
throw new Exception(string.Format("Field '{0}' not found in type hierarchy.", fieldName));
}
fi.SetValue(target, value);
}
And then:
Mine m = new Mine();
SetField(m, "_baseField", 10);
Extension method:
/// <summary>
/// Returns the FieldInfo matching 'name' from either type 't' itself or its most-derived
/// base type (unlike 'System.Type.GetField'). Returns null if no match is found.
/// </summary>
public static FieldInfo GetPrivateField(this Type t, String name)
{
const BindingFlags bf = BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.DeclaredOnly;
FieldInfo fi;
while ((fi = t.GetField(name, bf)) == null && (t = t.BaseType) != null)
;
return fi;
}
I think you need to add the System.Reflection.BindingFlags.Instance flag. Use | to combine it with the NonPublic flag.
EDIT:
Looks like BrokenGlass has it right. I wrote the following quick test.
var fields = test.GetType().BaseType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var field in fields)
{
System.Console.WriteLine(field.Name);
}
It correctly reports the field you were looking for. (Test is derived from BaseValidator)
If hierarchy is static, the simplest way to do this:
var field = typeof(SuperClass1).GetField("_privateBaseField",System.Reflection.BindingFlags.NonPublic);

Categories

Resources