Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude interface implementation members through reflection

I have the following Interface, and implementation:

public interface INew
{
    string TestString { get; }
}

public class PurchaseOrder : INew
{
    public string OrderNo { get; set; }

    public string TestString
    {
        get { return "This is a test string"; }
    }
}

I am trying to reflect out the OrderNo part of the PurchaseOrder object, using the following code:

var props = p.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy);
foreach (var prop in props)
{
    Console.WriteLine(prop.Name);
}

My output is returning the TestString property also. I have searched for ways to exclude implemented interface members but can only find items to include it. Can anybody show me how i can exclude such items?

like image 727
Dominic Cotton Avatar asked Aug 31 '16 08:08

Dominic Cotton


2 Answers

Here is a solution using the GetInterfaceMap Method:

var interfaceMethods = typeof(PurchaseOrder)
    .GetInterfaces()
    .Select(x => typeof(PurchaseOrder).GetInterfaceMap(x))
    .SelectMany(x => x.TargetMethods).ToArray();

var propsNotFromInterface= typeof(PurchaseOrder)
    .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy)
    .Where(x => !x.GetAccessors(true).Any(y => interfaceMethods.Contains(y))).ToArray();

Console.WriteLine(propsNotFromInterface.Length);

You can refactor this into a generic method very easily.

like image 145
thehennyy Avatar answered Sep 22 '22 14:09

thehennyy


You can try excluding properties that defined in INew like:

PurchaseOrder p = new PurchaseOrder();
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy;
PropertyInfo[] iNewPropertyInfos = typeof(INew).GetProperties(bindingFlags);
var props = p.GetType().GetProperties(bindingFlags).Where(x => iNewPropertyInfos.All(y => y.ToString() != x.ToString()));
foreach (var prop in props)
{
    Console.WriteLine(prop.Name);
}

Update.

More generic approach would be moving that logic into generic function:

private static IEnumerable<PropertyInfo> GetPropertiesExcept<T>(object p)
{
    BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly |
                                BindingFlags.FlattenHierarchy;
    PropertyInfo[] iNewPropertyInfos = typeof (T).GetProperties(bindingFlags);
    return p.GetType().GetProperties(bindingFlags).Where(x => iNewPropertyInfos.All(y => y.ToString() != x.ToString()));
}

And usage:

PurchaseOrder p = new PurchaseOrder();
IEnumerable<PropertyInfo> propertiesExcept = GetPropertiesExcept<INew>(p);
like image 23
Vladimirs Avatar answered Sep 22 '22 14:09

Vladimirs