GetProperties() to return all properties for an interface inheritance hierarchy
I've tweaked @Marc Gravel's example code into a useful extension method encapsulates both classes and interfaces. It also add's the interface properties first which I believe is the expected behaviour.
public static PropertyInfo[] GetPublicProperties(this Type type)
{
if (type.IsInterface)
{
var propertyInfos = new List<PropertyInfo>();
var considered = new List<Type>();
var queue = new Queue<Type>();
considered.Add(type);
queue.Enqueue(type);
while (queue.Count > 0)
{
var subType = queue.Dequeue();
foreach (var subInterface in subType.GetInterfaces())
{
if (considered.Contains(subInterface)) continue;
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
var typeProperties = subType.GetProperties(
BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance);
var newPropertyInfos = typeProperties
.Where(x => !propertyInfos.Contains(x));
propertyInfos.InsertRange(0, newPropertyInfos);
}
return propertyInfos.ToArray();
}
return type.GetProperties(BindingFlags.FlattenHierarchy
| BindingFlags.Public | BindingFlags.Instance);
}
Reflecting over all properties of an interface, including inherited ones?
An answer of sorts is to be found in an annotation to the .NET framework version 3.5-specific MSDN page on GetProperties(BindingFlags bindingFlags)
:
Passing BindingFlags.FlattenHierarchy
to one of the Type.GetXXX methods,
such as Type.GetMembers, will not
return inherited interface members
when you are querying on an interface
type itself.[...]
To get the inherited members, you need
to query each implemented interface
for its members.
Example code is also included. This comment was posted by a Microsoftie, so I would say you can trust it.
GetProperties for inherited/child class with appropriate BindingFlags does not return expected properties
public readonly Guid Id
is a field, not a property. Use the GetField
method instead:
typeof(ChildClass).GetField("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
You can check to see if it is readonly
by looking at the IsInitOnly
property of the FieldInfo
class.
var result = typeof(ChildClass).GetField("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
Assert.IsTrue(result.IsInitOnly);
Using attribute of inherited property from an interface
Child
does not have any custom attributes, ITest
has them, so you will have to call GetCustomAttributes
on the members of ITest
.
There is a difference between inheritance and implementation. Inheritance would be fine if Child
was derived from some base class that had a y
property decorated with My1Attribute
.
In your case, Child
implements ITest
and ITest
is a different type, outside of the inheritance hierarchy.
void Main()
{
var my1Attribute = typeof(ITest).GetProperty("y").GetCustomAttribute(typeof(My1Attribute)) as My1Attribute;
Console.WriteLine(my1Attribute.x); // Outputs: 0
}
[AttributeUsage(AttributeTargets.Property, Inherited = true)]
class My1Attribute : Attribute
{
public int x { get; set; }
}
interface ITest
{
[My1]
int y { get; set; }
}
class Child : ITest
{
public Child() { }
public int y { get; set; }
}
Reflection : Getting members from inherited interface, but not from inherited class
You can go about this in a number of ways, depending on your exact aim.
One idea is to get all properties normally then filter out those coming from class A
using DeclaringType
, e.g.
var typeOfA = typeof(A);
var notFromA = allMembers.Where(
p => p.DeclaringType != typeOfA && !p.DeclaringType.IsSubclassOf(typeOfA));
Or of course you can simply ignore the base class completely and get only the members coming from implemented interfaces, e.g.
var members = typeof(B).GetInterfaces().SelectMany(i => i.GetMembers());
This will give you all members of B
that are implementations of interface members -- not necessarily all of B's declared members, and it will include interface members that A
has implemented.
In general the correct way to do this depends on the exact requirements, but I feel the question is not precise enough in its current form.
Related Topics
How to Embed an Application Manifest into an Application Using VS2008
Right Aligning Text in PDFpcell
How Does Startcoroutine/Yield Return Pattern Really Work in Unity
How to Set the Wix Installer Version to the Current Build Version
Why Is Graphics.Measurestring() Returning a Higher Than Expected Number
How to Use C# to Sanitize Input on an HTML Page
Proper JSON Serialization in MVC 4
Create PDF in Memory Instead of Physical File
Hashset That Preserves Ordering
Casting List<T> - Covariance/Contravariance Problem
How Much Faster Is C++ Than C#
What Is Func, How and When Is It Used
C#:Is Variance (Covariance/Contravariance) Another Word for Polymorphism
Embed Unity3D App Inside Wpf Application