2014-01-28 2 views
0

Есть ли чистый способ запроса Type для свойств и фильтрации тех, которые поступают из интерфейса?Получить свойства класса без свойств, полученных из заданного интерфейса

Скажем, у меня есть класс и интерфейс

public interface IFoo 
{ 
    string Bar { get; set; } 
} 

public class Foo : IFoo 
{ 
    public string Bar { get; set; } 
    public string Baz { get; set; } 
} 

И я хочу, чтобы получить массив PropertyInfo-х, которые содержат только Baz свойство.

Edit:

Это то, что я сейчас ... Я знаю, что это не идеально, но это своего рода делает работу.

var allProperties = typeof(T).GetProperties(); 
var interfaceMethods = typeof(T).GetInterfaceMap(typeof(IFoo)).TargetMethods; 
return allProperties.Where(x => !interfaceMethods.Contains(x.GetGetMethod()) || !interfaceMethods.Contains(x.GetSetMethod())).ToArray(); 
+0

Кажется немного странным это нужно , Полагайте, что 'Foo' может и не быть, в настоящее время реализует' IFoo' (этот интерфейс еще не существует). Ваш код вернет 'Bar' и' Baz'. Затем кто-то приходит и решает создать интерфейс «IFoo» и использовать его в Foo. Обычно это не считается «нарушением изменений» - и все же это изменит поведение кода, о котором вы просите. –

+0

Это динамическое поведение, о котором вы упомянули, это именно то, что я ищу. Если он реализует IFoo, я хочу только «Baz», и когда это не так, я хочу «Bar» и «Baz». – ppiotrowicz

ответ

1

Похоже, что вы хотите использовать InterfaceMapping:

private static bool IsInterfaceImplementation(PropertyInfo p, InterfaceMapping interfaceMap) 
    { 
     var getterIndex = Array.IndexOf(interfaceMap.TargetMethods, p.GetGetMethod()); 
     var setterIndex = Array.IndexOf(interfaceMap.TargetMethods, p.GetSetMethod()); 

     return getterIndex != -1 || setterIndex != -1; 
    } 

    private static PropertyInfo[] GetPropertiesExcludeInterfaceImplementation(Type type, Type interfaceType) 
    { 
     var interfaceMap = type.GetInterfaceMap(interfaceType); 

     return type 
      .GetProperties() 
      .Where(p => !IsInterfaceImplementation(p, interfaceMap)) 
      .ToArray(); 
    } 
+0

Да, это то, что я уже использую. Я просто подумал, что для этого есть лучшее решение. – ppiotrowicz

0

Вы можете загрузить все интерфейсы, реализованные вашим классом, и получить все свойства этих интерфейсов. При получении свойства вашего класса вы можете проверить, является ли свойство уже определено одним из интерфейсов:

var interfaceProperties = typeof(Foo) 
    .GetInterfaces() 
    .SelectMany(i => i.GetProperties()) 
    .ToList(); 

var properties = typeof(Foo) 
    .GetProperties() 
    .Where(p => !interfaceProperties.Any(ip => ip.Name==p.Name && ip.PropertyType==p.PropertyType)); 
+1

Что делать, если 'Foo' содержит два свойства' Bar'? То есть 'public string Bar {get; задавать; } \t \t string IFoo.Bar {get; задавать; } '- публичный - это * не * реализация интерфейса' IFoo', и поэтому (предположительно) не следует игнорировать. –

+0

хорошо, это правильно ... Мне нужно подумать об этом :) –

+0

@Damien_The_Unbeliever да, я собирался это упомянуть. Благодаря! – ppiotrowicz

Смежные вопросы