Хотя (принятый) ответ @ Джереми Тодда работает и является широко распространенным решением проблемы, у него есть недостаток: он не очень удобен для IoC и сериализации, поскольку ваш класс не может быть правильно сконструирован с использованием new
. Позвольте мне представить общее решение с использованием некоторых возможностей C #. Обратите внимание, что это решение не требует, чтобы вы использовали фабричный шаблон или вызывали что-либо после создания объекта, и оно работает с любым классом, просто реализуя интерфейс с помощью одного метода.
Сначала мы объявляем интерфейс, который должны реализовать наши классы:
public interface IInitialize {
void OnInitialize();
}
Затем мы добавляем статический класс расширения для этого интерфейса и добавляем метод Initialize:
public static class InitializeExtensions
{
public static void Initialize<T>(this T obj) where T: IInitialize
{
if (obj.GetType() == typeof(T))
obj.OnInitialize();
}
}
Теперь, если нам нужен класс и все его потомки для вызова инициализатора сразу после того, как объект полностью построен, все, что нам нужно сделать, это реализовать IInitialize
и добавить строку в конструкторе:
public class Parent : IInitialize
{
public virtual void OnInitialize()
{
Console.WriteLine("Parent");
}
public Parent()
{
this.Initialize();
}
}
public class Child : Parent
{
public Child()
{
this.Initialize();
}
public override void OnInitialize()
{
Console.WriteLine("Child");
}
}
public class GrandChild : Child
{
public GrandChild()
{
this.Initialize();
}
public override void OnInitialize()
{
Console.WriteLine("GrandChild");
}
}
Хитрость в том, что когда производный класс вызывает метод расширения Initialize
, он будет подавлять любые вызовы, не сделанные из фактического класса.