Get all static properties from a class - c#

I know that there are many questions like this, but I couldn't find any answer to what I'm trying to do.
Considering the following abstract class:
public abstract class TestBase
{
public static ITest Test => Container.Resolve<ITest>();
public static ITest1 Test1 => Container.Resolve<ITest1>();
public static ITest2 Test2 => Container.Resolve<ITest2>();
public static ITest3 Test3 => Container.Resolve<ITest3>();
}
I'm trying to get all the properties that inherit from an interface IDummy like this:
var members = typeof(TestBase).GetMembers(BindingFlags.Static | BindingFlags.Public)
.Where(f => f.GetType().IsAssignableFrom(typeof(IDummy)) == true);
but the list is empty. Without adding the where clause ".Where(f => f.GetType().IsAssignableFrom(typeof(IDummy)) == true)" I get all the results including the getters for the properties.
Probably is something trivial, but as I'm not so familiar with reflection I can't figure out what I'm doing wrong.

What you get back from GetMembers is MemberInfo instances (or, for fields, FieldInfo instances). Hence, you cannot check these objects directly for being assignable from IDummy.
What you actually want to do is filter the MemberInfo objects for fields, then check the FieldType property of each of these objects:
var members = typeof(TestBase).GetMembers(BindingFlags.Static | BindingFlags.Public)
.OfType<FieldInfo>()
.Where(f => typeof(IDummy).IsAssignableFrom(f.FieldType));
Also, note that I turned around the subject and object of the IsAssignableFrom call, as also suggested in Patrick's comment.
As I just noticed, your example seems to show properties rather than fields. The general technique is the same, though; just use PropertyInfo and PropertyType rather than FieldInfo and FieldType, respectively.
Lastly, rather than filtering for PropertyInfo yourself, you could also use the one of the overloads of the GetProperties method directly.

Related

Getting Nested Types from Higher in Hierarchy in C#

I have a few classes called SortMethod which inherit from an abstract class called ASortMethod. Each of these classes is nested in another class. Right now, I'm dealing with the SortMethod inside of a class called CitationCollection.
There's another class I'm dealing with called CustomSortDictionary. This has to handle the given SortMethod type, but it's unknown which SortMethod type will be given, so I store a variable Type sortMethod in CustomSortDictionary.
This means I unfortunately have to deal with lots of messy reflection. Within the given Type sortMethod, there are two main things I'm looking to access. The first I was able to access using the below code, but the second I'm having trouble getting to.
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;
// Accessing the first
MethodInfo m = SortMethod.GetMethod("ConstructCustomSortMethods", bindingFlags);
m.Invoke(null, null);
// Accessing the second
IDCollection customSort = (IDCollection)SortMethod.GetNestedType("CustomSort", bindingFlags).GetField("Methods").GetValue(null);
I've tried a few different combinations of BindingFlags to try to get to the nested type in the second piece of code, but I can't access it. I think the issue is that SortMethod.CustomSort.Methods is declared within ASortMethod, which is one step up the hierarchical ladder from CitationCollection.SortMethod.
How would I properly access this second item using reflection?
See this link for the full code.
UPDATE:
I found this from Microsoft's website, which may explain my issue:
BindingFlags.FlattenHierarchy
Specifies that public and protected static members up the hierarchy should be returned. Private static members in inherited classes are not returned. Static members include fields, methods, events, and properties. Nested types are not returned.
Your sort method type looks like this right?
public enum SortType { Ascend, Descend, FlyingTriangle }
You may want to use an interface so that all methods implementing it are required to either accept or reject a requested sort.
Example
public interface ISortable
{
public bool IsValidContext(object record, SortType type);
}
public class SortAlpha : ISortable
{
public bool IsValidContext(object record, SortType type)
{
return type == SortType.Ascend ? true : false; // example
}
}
public class SortBeta : ISortable
{
public bool IsValidContext(object record, SortType type)
{
return type == SortType.Descend && record is HtmlDocument; // example
}
}
You can have a method iterate trough the classes implementing the interface to find and return the right one.
Since the type CustomSort is always nested in ASortMethod you could just get it directly:
((IDCollection)typeof(ASortMethod.CustomSort).GetField("Methods").GetValue(null)).Add(ref name);
When you can not for some reason you could walk up the base types until you reach object to find the enclosing type of CustomSort
((IDCollection)FindBase(SortMethod).GetNestedType("CustomSort", bindingFlags).GetField("Methods").GetValue(null)).Add(ref name);
static Type FindBase(Type t)
{
if (t.BaseType != typeof (object))
return FindBase(t.BaseType);
return t;
}

Alternative to: Static class as Generic-Parameter

I do have a lot of static classes that represent different states in different modules. However they share common algorithms that extract its information.
public static class Constants
{
public static readonly int A = 0;
}
So for now I have for each class multiple static functions that does this. They only differ in the type of the static class that is processed (and its overall name).
public static SelectListItem getConstantsSelectListItem()
{ // pseudo example
return new SelectListItem { Text = "A" , Value = Constants.A };
}
To remove current and avoid future codebloat, I'd like to use reflection on the static classes. Here's my approach, that would do the job (if it was possible):
public static ReturnType getProperties< T >()
{ // basically same logic as getConstantsSelectListItem
var propertyList = typeof( T ) .GetFields( BindingFlags.Public | BindingFlags.Static ).ToList();
foreach( var item in propertyList )
{
var curConstant = (int)( item.GetValue( null ) );
// do some work here..
}
}
var constantsProperties = getProperties<Constants>();
The error is:
static types cannot be used as argument types
I have read, that for generics only instances (and therefore no static classes) can be used.
What would be a good way to make something similar work?
The question C# - static types cannot be used as type arguments explains very well that this behavior is intended.
It doesn't tell what you should do. In my opinion you could use a singleton pattern to keep one instance of that class. One benefit of this is that you can use inheritance too, so you don't need reflection to do the trick you do now, you can just rely on the base class' method signature.
You can just pass a Type object as an argument instead of using generics. Since you have to do typeof(T) .GetFields( anyway, it's not like you have any static type safety that you're losing.
The other suggestion I would strongly make is to use dictionaries mapping strings to integers to represent your collections of constants. Using reflection like this is just giving you pain for no good reason, enforces weird, almost ritualistic rules on developers ("this static class is magic, don't add any strings"), and has worse performance.

C#: How to reflect a class to get its properties of pre defined data type

I have a class 'Employee', it has following members:
//[membername,type]
[Name,string]
[DOB,DateTime]
[DateOfHire,DateTime]
[TerminationDate,DateTime?]
[AddressChanges,List<string>]
Here, I need to reflect and get all the properties except the ones that are of collection type.
In this example,except AddressChanges, I need to get all the members.
Thanks.
Depending what you mean by 'collection', something like this will work:
var notCollectionProperties =
typeof(Employee)
.GetProperties(BindingFlags.Public|BindingFlags.Instance)
.Where(prop => !typeof(ICollection).IsAssignableFrom(prop.PropertyType));
More generally you might want to use IEnumerable rather than ICollection.
Use reflection to enumerate the properties and exclude those with a collection type. For example:
Type myType = typeof(TargetClass);
foreach(PropertyInfo propertyInfo in myType.GetProperties())
{
if(propertyInfo.PropertyType is ...)
{
// Handle cases
}
}

Identifying properties that override base properties or implement interfaces

I am given:
A class "T" which implements properties that are decorated with Attributes that I am interested in.
A PropertyInfo "p" representing a property belonging to (1) an interface "I" that T implements, (2) a base class "B" that T inherits from, or (3) the class T itself.
I need to get the Attributes defined on (or inherited by) the properties in T, even if p's DeclaringType is an interface that T implements or a class that T inherits from. So I need a way to get from p to the PropertyInfo that actually exists on T. Thus it seems that there are 3 cases:
p.DeclaringType == typeof(T)
This is the trivial case. I can iterate through T's properties until I find the match. Example:
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(property => property == p)
p.DeclaringType == typeof(I) where I is an interface that T implements
This is more complicated. I found that I can use an InterfaceMapping to find the corresponding implementation of the p in T. It seems kind of hackish, but here what works:
if (p.DeclaringType.IsInterface &&
typeof(T).GetInterfaces().Contains(p.DeclaringType))
{
InterfaceMapping map = typeof(T).GetInterfaceMap(p.DeclaringType);
MethodInfo getMethod = p.GetGetMethod();
for (int i = 0; i < map.InterfaceMethods.Length; i++)
{
if (map.InterfaceMethods[i] == getMethod)
{
MethodInfo target = map.TargetMethods[i];
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(property => property.GetGetMethod() == target);
}
}
}
p.DeclaringType == typeof(B) where B is a class that T inherits from
I have not yet been able to figure out how to identify the property on T that overrides a virtual property p defined in Ts base class B.
So my questions are
In case 3 how do I find the PropertyInfo on T that overrides the property p on B?
Is there a better way to do all three? Perhaps a way to unify the three cases.
I think you're missing a case : it is possible that T just inherits the property from B, without overriding it (unless you know for sure this won't happen in your specific scenario).
Anyway, you just need to search the property by name, using typeof(T).GetProperty, since there can't be 2 properties with the same name in a given class (unlike methods, which can have several overloads). However, you need to watch out for the case where T hides the property inherited from B, using the new modifier. To handle that case, you can check the Attributes of the property's getter method (obtained with GetGetMethod) : if the NewSlot flag is present, it hides the inherited getter.
I found a way to answer case 3. The key is MethodInfo.GetBaseDefinition
if (typeof(T).IsSubclassOf(p.DeclaringType))
{
MethodInfo baseDefinition = p.GetGetMethod().GetBaseDefinition();
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(property => property.GetGetMethod().GetBaseDefinition() == baseDefinition);
}
However this only works for properties that have been overridden on T.
Edit:
By comparing the following, it doesn't matter if the properties have or haven't been overriden on T:
property.GetGetMethod().GetBaseDefinition().MetadataToken == baseDefinition.MetadataToken

in C#, Is there anyway to determine a class's members at runtime?

Suppose I have a class named foo, and it has 3 public members foo1, foo2, and foo3.
Now suppose I'm writing a function that takes an instance of class foo as a parameter, but when I'm writing this function I have no idea what public members it has.
Is there a way for me to determine at run-time that it has public members foo1, foo2, foo3 AND ONLY foo1, foo2, foo3. IE - find out what all the public members are?
And can I also determine their types?
Well, that's what Reflection is there for :
Type myObjectType = typeof(foo);
System.Reflection.FieldInfo[] fieldInfo = myObjectType.GetFields();
foreach (System.Reflection.FieldInfo info in fieldInfo)
Console.WriteLine(info.Name); // or whatever you desire to do with it
You could use reflection:
// List all public properties for the given type
PropertyInfo[] properties = foo.GetType().GetProperties();
foreach (var property in properties)
{
string propertyName = property.Name;
}
You should be aware that there could be an additional overhead when using reflection because types are evaluated at runtime.
Have a look at the .net reflection namespace:
http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx
This is a job for reflection. Look into methods like:
myFoo.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
This will return all public, instance methods that the type has. You can then look through the returned results and determine if this class meets your criteria. There are equivalent methods as well for other types of members, such as GetFields(...), GetProperties(...), etc.
Basically you want to get to know the Type class, which is the core of C#'s reflection capabilities.
foreach(PropertyInfo pi in yourObject.GetType().GetProperties())
{
Type theType = pi.PropertyType;
}
Following article on MSDN should help you determine the methods of a type

Categories