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);
}
Related
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;
}
Take for example the below sample code:
public class TestMultipleAttributesAttribute : AttributeWithPriority
{
public string HelpMessage { get; set; }
}
public class Student
{
[TestMultipleAttributes(HelpMessage = "Student")]
public virtual string Name { get; set; }
}
public class SpecificStudent : Student
{
[TestMultipleAttributes(Priority = 100, HelpMessage = "SpecificStudent")]
public override string Name { get; set; }
}
Is there any way by reflection how I can get both the two instances of the TestMultipleAttributes for the same overriden property?
I tried the below code:
[Test]
public void testMultipleAttribs()
{
var property = typeof(SpecificStudent).GetProperties().FirstOrDefault(x => x.Name == "Name");
var attribList = property.Attributes; //returns none
var customAttribs = property.CustomAttributes.ToList(); //returns 1
var customAttribs2 = property.GetCustomAttributes(inherit: true);// returns 1
int k = 5;
}
One solution that came in mind is to find the property.DeclaringType, and repeating the process , and get the attributes for it. However, I don't find it an elegant way to do this and was wondering if there is a better way.
You have only one attribute named TestMultipleAttributes and you overwrote it.The attribute have more than one property (Priority and HelpMessage) its working correctly.
You can create more "really" attributes like so StudentAttribute and SpecificStudentAttribute.
I don't know...this is relatively elegant (though I'm sure I'm missing at least one special case). It should enumerate all the custom attributes on an overridden or virtual property in the inheritance chain in nearest-first order:
public static IEnumerable<Attribute> AllAttributes( PropertyInfo pi )
{
if ( pi != null )
{
// enumerate all the attributes on this property
foreach ( object o in pi.GetCustomAttributes( false ) )
{
yield return (Attribute) o ;
}
PropertyInfo parentProperty = FindNearestAncestorProperty(pi) ;
foreach( Attribute attr in AllAttributesRecursive(parentProperty) )
{
yield return attr ;
}
}
}
private static PropertyInfo FindNearestAncestorProperty( PropertyInfo property )
{
if ( property == null ) throw new ArgumentNullException("property") ;
if ( property.DeclaringType == null ) throw new InvalidOperationException("all properties must belong to a type");
// get the property's nearest "ancestor" property
const BindingFlags flags = BindingFlags.DeclaredOnly
| BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Static | BindingFlags.Instance
;
Type t = property.DeclaringType.BaseType ;
PropertyInfo ancestor = null ;
while ( t != null && ancestor == null )
{
ancestor = t.GetProperty(property.Name,flags) ;
t = t.BaseType ;
} ;
return ancestor ;
}
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);
}
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);