Ну, грязным способом может быть проверка вручную соответствия меток.
метод для проверки подписей может выглядеть следующим образом:
public static bool HasSameSignature(MethodInfo potentiallyHidingMethod, MethodInfo baseMethod)
{
//different name, therefore not same signature
if (potentiallyHidingMethod.Name != baseMethod.Name)
return false;
//now we check if they have the same parameter types...
var potentiallyHidingMethodParameters = potentiallyHidingMethod.GetParameters();
var baseMethodParameters = baseMethod.GetParameters();
//different number of parameters, therefore not same signature
if (potentiallyHidingMethodParameters.Length != baseMethodParameters.Length)
return false;
for (int i = 0; i < potentiallyHidingMethodParameters.Length; i++)
{
//if a parameter type doesn't match, it's not the same signature
if (potentiallyHidingMethodParameters[i].ParameterType != baseMethodParameters[i].ParameterType)
return false;
}
//if we've gotten this far, they have the same name and parameters,
//therefore, it's the same signature.
return true;
}
Тогда это вопрос проверки полученных методов интерфейса, чтобы увидеть, если они скрывают (или соответствие подписи) любого из методов базового интерфейса:
Type type = typeof(IInterfaceWithNewMethod);
var potentiallyHidingMethods = type.GetMethods();
var baseTypeMethods =type.GetInterfaces()
.SelectMany(@interface => @interface.GetMethods());
var hidingMethods = potentiallyHidingMethods
.Where(hiding => baseTypeMethods.Any(baseMethod => HasSameSignature(hiding, baseMethod)));
Примечание: это немного наивная реализация. Я не удивлюсь, если есть более простой способ или угловой случай, который это не охватывает.
EDIT: Немного неправильно понял желаемый результат. Используя код выше, это даст вам все методы базового интерфейса, плюс полученные методы интерфейса, но отфильтрованы любые методы базового интерфейса, которые были скрыты в производном интерфейсе:
var allMethodsButFavouringHiding = potentiallyHidingMethods.Concat(
baseTypeMethods.Where(baseMethod => !potentiallyHidingMethods.Any(potentiallyhiding => HasSameSignature(potentiallyhiding, baseMethod))));
EDITx2: Я сделал тест дал следующие интерфейсы:
public interface IBaseInterface
{
string BaseMethodTokeep();
string MethodToHide();
string MethodSameName();
}
public interface IInterfaceWithNewMethod : IBaseInterface
{
new string MethodToHide();
new string MethodSameName(object butDifferentParameters);
string DerivedMethodToKeep();
}
в результате с коллекцией MethodInfo
:
MethodToHide (IInterfaceWithNewMethod)
MethodSameName (IInterfaceWithNewMethod)
DerivedMethodToKeep (IInterfaceWithNewMethod)
BaseMethodTokeep (IBaseInterface)
MethodSameName (IBaseInterface)
Так он держит любой базовый интерфейс мето ds, которые не скрыты, какие-либо производные интерфейсные методы (которые скрываются или иным образом), и чтит любые изменения подписи (то есть различные параметры, которые не приведут к скрытию).
EDITx3: Добавлен еще один тест с перегрузками:
public interface IBaseInterface
{
string MethodOverloadTest();
string MethodOverloadTest(object withParam);
}
public interface IInterfaceWithNewMethod : IBaseInterface
{
new string MethodOverloadTest();
}
С результатами:
MethodOverloadTest() for IInterfaceWithNewMethod
MethodOverloadTest(object) for IBaseInterface
Не понимаю, без нового ключевого слова также он будет вести себя одинаково правильно? AFAIK нет никакой разницы в применении ключевого слова 'new'. Я что-то упускаю? Какова конечная цель? –
@SriramSakthivel Да, «новое» ключевое слово является необязательным. Важно то, что один метод затеняет другой. Я работаю над [этой проблемой] (https://github.com/AutoFixture/AutoFixture/issues/306) для AutoFixture, и мне нужно иметь возможность использовать отражение для настройки всех методов макета интерфейса + его базы интерфейсы. Однако, если метод тени другого, я должен * не * настроить теневой метод. – dcastro