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);
Related
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);
}
Consider the following C# class declaration:
public class MyClass {
private enum Colours { Red, Green, Blue }
}
Which is sat in a separate class library/DLL.
Given just the typeof(MyClass) object (System.Type), is there any way to check if the class contains an enum called Colours at runtime and if so return it's corresponding System.Type object?
What I'm trying to do is write some generic code that's given the type of a class and determine if contains a specifically named enum inside and then query the values in the enum.
I know how to use Reflection to query things like GetFields, GetProperties etc. but there isn't a GetClasses or GetEnums method in System.Type.
I suspect this kind of information is in the assembly?
Just do:
var res = typeof(MyClass).GetNestedType("Colours", BindingFlags.NonPublic);
Test res != null to see if such type exists.
Then test res.IsEnum to see if the nested type is an enum.
Addition: If the nested type is occasionally nested public, use BindingFlags.NonPublic | BindingFlags.Public instead.
I came up with following two methods:
public class MyClass {
private enum Colours { Red, Green, Blue }
private class Inner {
private enum Colours { Black, White }
}
}
class Program {
static void Main(string[] args) {
Type coloursType;
// 1. enumerator
coloursType = typeof(MyClass).EnumerateNestedTypes()
.Where(t => t.Name == "Colours" && t.IsEnum)
.FirstOrDefault();
// 2. search method
coloursType = typeof(MyClass).FindNestedType(t => t.Name == "Colours" && t.IsEnum);
if(coloursType != null) {
Console.WriteLine(string.Join(", ", coloursType.GetEnumNames()));
} else {
Console.WriteLine("Type not found");
}
Console.ReadKey();
}
}
public static class Extensions {
public static IEnumerable<Type> EnumerateNestedTypes(this Type type) {
const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic;
Queue<Type> toBeVisited = new Queue<Type>();
toBeVisited.Enqueue(type);
do {
Type[] nestedTypes = toBeVisited.Dequeue().GetNestedTypes(flags);
for(int i = 0, l = nestedTypes.Length; i < l; i++) {
Type t = nestedTypes[i];
yield return t;
toBeVisited.Enqueue(t);
}
} while(toBeVisited.Count != 0);
}
public static Type FindNestedType(this Type type, Predicate<Type> filter) {
const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic;
Type[] nestedTypes = type.GetNestedTypes(flags);
foreach(var nestedType in nestedTypes) {
if(filter(nestedType)) {
return nestedType;
}
}
foreach(var nestedType in nestedTypes) {
Type result = FindNestedType(nestedType, filter);
if(result != null) {
return result;
}
}
return null;
}
}
var types = typeof(MyClass).Assembly.DefinedTypes;
foreach (var type in types)
{
Console.WriteLine(type.Name);
}
Output:
MyClass
Colours
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;
}
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.
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);
}