У меня есть абстрактный класс, определенный другой сборкой (не редактируемый):
public abstract class A
{
public void Run()
{
Go("Hello World");
}
protected virtual void Go(string message)
{
// Do Nothing
}
}
Теперь у меня есть библиотека, которую я хочу наследовать от этого класса, которая реализует Go ().Хитрость в том, что я не хочу, чтобы кто-то из моих наследников мог переопределить мою реализацию Go (), но я также не хочу менять подпись каким-либо образом.Я на самом деле хочу, чтобы обе реализации были вызваны.Вот что я получил до сих пор:
public abstract class B_Intercept : A
{
protected sealed override void Go(string message)
{
Console.WriteLine(message);
Go_Impl(message);
}
internal abstract void Go_Impl(string message);
}
public abstract class B : B_Intercept
{
protected new virtual void Go(string message)
{
}
internal override void Go_Impl(string message)
{
Go(message);
}
}
Теперь мои конечные пользователи могут переключать наследование своего класса с A на B без эффекта (кроме моего Console.WriteLine).
public class C : A // This can be changed to B with no other edits
{
protected override Go(string message)
{
// Do stuff
}
}
Теперь исходной библиотеке можно дать экземпляр C, он будет помечен как A, а исходная библиотека вызовет Run ().Run будет использовать Go () B_Intercept, который выведет сообщение на консоль, а затем вызовет Go_Impl ().Go_Impl будет запущен в B, который вызовет функцию Go () B, которую можно переопределить с помощью C.
Это кажется очень сложным.
В методах есть дополнительное преимущество (онине могу вызвать Go_Impl напрямую), но все еще есть дыры (они могут вызывать base.Go).Я думаю, что эти дыры можно закрыть третьим слоем, но я не пробовал, и, честно говоря, я думаю, что это немного смешно.Но это все еще похоже на много стандартного кода.Есть также слабый побочный эффект B_Intercept, требующий быть публичным, а не внутренним, что необъяснимым образом увеличивает площадь моей библиотеки.
Есть ли более простой, более безопасный способ?