Зависит от определения «ближайший», это может быть не тривиальной задачей.
Tried-N-True
А сейчас давайте сосредоточимся на вашем пример. Я остановлюсь на этом с другой стороны по сравнению с решением @ OguzOzgul, но все равно буду использовать GetInterfaces
.
GetInterfaces
, в вашем случае возвращает типы интерфейса в тот же порядок, что и для наследования этих типов:
SubInterfaceClass
0: ISomeSubInterface
1: ISomeInterface
InterfaceClass
0: ISomeInterface
Как вы могли видеть, вы можете найти «ближайший» тип реализации, найдя наименьший возможный индекс, где ISomeInterface
находится в. А в вашем случае ISomeInterface
находится в позиции 0 в списке интерфейсов InterfaceClass
, поэтому вы должны выбрать InterfaceClass
.
Это можно сделать с помощью агрегатора:
private T GetClosetImplementationAsPerReflection<T>()
where T : ISomeInterface
{
var result = _objects.Where(IsOfType<T>)
.Aggregate(
// Default entry
new { obj = default(T), rank = int.MaxValue },
// Aggregator
(currentEntry, o) =>
{
// Find all interface types implemented by the instance type
// Because your class types do not have base type, the order of interfaces
// appear in the list is same as how the interfaces are inherited.
// e.g.
// SubInterfaceClass: 0->ISomeSubInterface, 1->ISomeInterface
// InterfaceClass: 0->ISomeInterface
var entryFound = o.GetType()
.GetInterfaces()
.Select((interfaceType, index) => new { interfaceType, index })
.First(_ => _.interfaceType == typeof(T));
// Now you could find the type / instance with ISomeInterface
// at the lowest possible index
if (entryFound.index < currentEntry.rank)
{
return new { obj = (T)o, rank = entryFound.index };
}
else
{
return currentEntry;
}
});
return result.obj;
}
Однако
Вышесказанное является проверенным решением только для вашего тривиального случая. На самом деле такого «самого близкого» определения не существует.
Компилятор компилирует SubInterfaceClass
в следующее:
private class SubInterfaceClass : ISomeSubInterface, ISomeInterface
{
}
Так что ISomeInterface
, возможно, одинаково близко к SubInterfaceClass
по сравнению с InterfaceClass
. Хотя вы можете утверждать, что когда ISomeInterface
появляется после ISomeSubInterface
, тогда ISomeSubInterface
ближе, к сожалению, порядок не виден вашему коду. И это не гарантируется GetInterfaces
методом либо .
Мое предложение таково: определите, что значит для вас "ближайший", и, в частности, внедрите logi c для своих собственных "ближайших" .