Я прочитал этот похожий вопрос Я не ожидаю того же поведения, что и ОП, и я его не совсем понимаю, но у меня есть использование для защищенных членов внутри производных классов.
В Почему ключевое слово "this" требуется для вызова метода расширения из расширенного класса Эрик Липперт писал:
... Если вы находитесь вСценарий, в котором вы используете метод расширения для типа в этом типе, тогда у вас есть доступ к исходному коду.Почему вы сначала используете метод расширения?
... Учитывая эти два момента, бремя больше не ложится на разработчика языка, объясняющего, почему эта функция не существует.Теперь вам приходится объяснять, почему это так.С объектами связаны огромные затраты.
...
Поэтому я попытаюсь объяснить, почему я ожидал поведение и его пример использования.
Функция:
- Программист может получить доступ к защищенному элементу объекта
this
внутри метода расширения. - Когда защищенный член используется в методе расширения, вы можете использовать метод только внутри классов, производных от типа
this
объекта. - Защищенный метод расширения можно вызывать только с
this
Аргумент объект, который является тем же объектом, который доступен по ключевому слову this
в методе вызывающей стороны.
Сценарий использования в реальной жизни:
Я играю с созданием пользовательского редактора Visual Studio на основе WPFDesigner_XML .В настоящее время я пытаюсь разобраться в классе со следующей сигнатурой:
public sealed class EditorPane : WindowPane, IOleComponent, IVsDeferredDocView, IVsLinkedUndoClient
{...}
Многие методы используют сервисы Вот так:
void RegisterIndependentView(bool subscribe)
{
IVsTextManager textManager = (IVsTextManager)GetService(typeof(SVsTextManager));
if (textManager != null)
{
if (subscribe)
{
textManager.RegisterIndependentView(this, _textBuffer);
}
else
{
textManager.UnregisterIndependentView(this, _textBuffer);
}
}
}
Мне нравится фокусироваться на вещах, которыена самом деле важно, поэтому я написал вспомогательный метод, чтобы упростить такие методы.Например:
private void RegisterIndependentView(bool subscribe) {
if (with(out IVsTextManager tm)) return;
if (subscribe) tm.RegisterIndependentView(this, _textBuffer);
else tm.UnregisterIndependentView(this, _textBuffer);
}
Метод with
выглядит следующим образом:
private bool with<T>(out T si) {
si = (T)GetService(getServiceQueryType<T>());
return si == null ? true : false;
}
И я поместил getServiceQueryType<T>()
в статический класс:
public static class VSServiceQueryHelper {
public static Type getServiceQueryType<T>() {
var t = typeof(T);
if (!serviceQueryTypesMap.ContainsKey(t)) throw new Exception($@"No query type was mapped in ""{nameof(serviceQueryTypesMap)}"" for the ""{t.FullName}"" interface.");
return serviceQueryTypesMap[t];
}
private static Dictionary<Type, Type> serviceQueryTypesMap = new Dictionary<Type, Type>() {
{ typeof(IVsUIShellOpenDocument), typeof(SVsUIShellOpenDocument) },
{ typeof(IVsWindowFrame), typeof(SVsWindowFrame) },
{ typeof(IVsResourceManager), typeof(SVsResourceManager) },
{ typeof(IVsRunningDocumentTable), typeof(SVsRunningDocumentTable) },
{ typeof(IMenuCommandService), typeof(IMenuCommandService) },
{ typeof(IVsTextManager), typeof(SVsTextManager) },
};
}
Это хорошо работает, но я также хотел бы разместить метод with
внутри VSServiceQueryHelper
как расширение, чтобы в любое время я мог бы расширить WindowsPane
, я мог бы просто поместить using static com.audionysos.vsix.utils.VSServiceQueryHelper;
вверху и использовать метод with
, которыйуже реализовано.
Проблема:
Я не могу сделать метод with
расширением, поскольку используемый им метод GetService
является защищенным членомWindowsPane
, который является базовым типом моего класса.Поэтому теперь мне нужно поместить реализацию with
в каждый класс, который расширяет WindowPane
, и это нарушает правило никогда не повторяться: /