Я нашел способ вызывать метод расширения с той же сигнатурой, что и у метода класса, однако он выглядит не очень элегантно. При игре с методами расширения я заметил некоторое недокументированное поведение. Пример кода:
public static class TestableExtensions
{
public static string GetDesc(this ITestable ele)
{
return "Extension GetDesc";
}
public static void ValDesc(this ITestable ele, string choice)
{
if (choice == "ext def")
{
Console.WriteLine($"Base.Ext.Ext.GetDesc: {ele.GetDesc()}");
}
else if (choice == "ext base" && ele is BaseTest b)
{
Console.WriteLine($"Base.Ext.Base.GetDesc: {b.BaseFunc()}");
}
}
public static string ExtFunc(this ITestable ele)
{
return ele.GetDesc();
}
public static void ExtAction(this ITestable ele, string choice)
{
ele.ValDesc(choice);
}
}
public interface ITestable
{
}
public class BaseTest : ITestable
{
public string GetDesc()
{
return "Base GetDesc";
}
public void ValDesc(string choice)
{
if (choice == "")
{
Console.WriteLine($"Base.GetDesc: {GetDesc()}");
}
else if (choice == "ext")
{
Console.WriteLine($"Base.Ext.GetDesc: {this.ExtFunc()}");
}
else
{
this.ExtAction(choice);
}
}
public string BaseFunc()
{
return GetDesc();
}
}
Что я заметил, так это то, что если бы я вызывал второй метод изнутри метода расширения, он вызывал бы метод расширения, который соответствовал сигнатуре, даже если был метод класса, который также соответствовал сигнатуре. Например, в приведенном выше коде, когда я вызываю ExtFunc (), которая в свою очередь вызывает ele.GetDesc (), я получаю возвращаемую строку «Extension GetDesc» вместо строки «Base GetDesc», которую мы ожидаем.
Тестирование кода:
var bt = new BaseTest();
bt.ValDesc("");
//Output is Base.GetDesc: Base GetDesc
bt.ValDesc("ext");
//Output is Base.Ext.GetDesc: Extension GetDesc
bt.ValDesc("ext def");
//Output is Base.Ext.Ext.GetDesc: Extension GetDesc
bt.ValDesc("ext base");
//Output is Base.Ext.Base.GetDesc: Base GetDesc
Это позволяет вам прыгать вперед и назад между методами класса и методами расширения по желанию, но требует добавления дублирующих "сквозных" методов, чтобы вы попали в "область", которую вы желаете. Я называю это сферой здесь из-за отсутствия лучшего слова. Надеюсь, кто-нибудь может дать мне знать, как это на самом деле называется.
Возможно, вы уже догадались по именам моих "сквозных" методов, которые я также поиграл с идеей передачи им делегатов в надежде, что один или два метода могут действовать как сквозные для нескольких методов с одинаковыми подпись. К сожалению, этого не произошло, поскольку после распаковки делегата он всегда выбирал метод класса, а не метод расширения, даже внутри другого метода расширения. «Сфера» больше не имеет значения. Я не очень часто использовал делегатов Action и Func, так что, возможно, кто-то более опытный мог бы понять эту часть.