Рассмотрим этот абстрактный класс
public abstract class Foo
{
public Injectable Prop {get;set;}
}
У меня есть приложение, которое я хочу улучшить и одновременно реорганизовать для простоты. У меня есть более 100 классов, которые вызывают одни и те же вещи (например, класс Injectable
), и я думаю, что это поведение можно абстрагировать и установить в базовый класс, и все будут наследоваться от этого базового класса, чтобы удалить код копирования/вставки.
Однако я хочу избежать копирования/вставки кода в файле конфигурации spring, определив объект Injectable
, а затем определив дочерний объект foreach и каждый класс, который наследуется от Foo
.
Я ищу способ установить свойства абстрактного класса, а затем все дочерние элементы, чтобы автоматически получать их через конфигурацию. Я хочу избежать создания абстрактного класса следующим образом:
public abstract class Foo
{
public Injectable Prop
{
get { return (Injectable)ContextRegistry.GetContext()["Injectable"]; }
}
}
спасибо за любые предложения
РЕДАКТИРОВАТЬ: чтобы немного усложнить ситуацию, дочерние классы представляют собой страницы ASP.NET, поэтому у меня есть ограниченный контроль над тем, как они генерируются.
В настоящее время я использую вышеупомянутый код, где абстрактный класс ссылается на созданный DI объект с идентификатором «Injectable». Я хотел бы избежать летающих строк
ОБНОВЛЕНИЕ (с решением)
Учтите: Классы
public abstract class BasePage : System.Web.UI.Page
{
public IInjectable FooProp {get;set;}
}
public abstract class BaseControl : System.Web.UI.UserControl
{
public IInjectable FooProp {get;set;}
}
public partial class ChildPage : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
FooProp.DoSomeThing();
}
}
public partial class ChildControl : BaseControl
{
protected void Page_Load(object sender, EventArgs e)
{
FooProp.DoSomeThing();
}
}
весна кфг...
<object id="Injectable" type="ConcreteInjectable">
<property name="SomeProp" value="Injected!!" />
</object>
<!--The requirement is to declare something like:-->
<object type="BasePage" abstract="true">
<property name="FooProp" ref="Injectable />
</object>
<!--it works for usercontrols too-->
<object type="BaseControl" abstract="true">
<property name="FooProp" ref="Injectable />
</object>
и эффект будет заключаться в том, что каждый наследник BasePage
будет иметь свойство FooProp
, введенное с тем, что я настроил.
это не имеет большого значения, если это может быть достигнуто с помощью какой-либо привязки к соглашению, но я не хочу использовать строки и использовать ссылки DI внутри моего кода.
Второе ОБНОВЛЕНИЕ И РЕШЕНИЕ благодаря tobsen и Erich Eichinger решение было найдено: во-первых, это не поддерживается изначально, но решение не очень уродливое и не нарушает нормы шаблона DI в плохой путь
Теперь вся необходимая конфигурация пружины приведена выше (в обновлении). Решение Эриха таково: сделайте IHttpModule
вот так:
public class PageModuleInjecter : IHttpModule
{
public void Dispose() {}
public void Init(HttpApplication context) {
context.PreRequestHandlerExecute += context_PreRequestHandlerExecute;
}
void context_PreRequestHandlerExecute(object sender, EventArgs e) {
IHttpHandler handler = ((HttpApplication )sender).Context.Handler;
if (handler is BasePage)
Spring.Context.Support.WebApplicationContext.Current
.ConfigureObject(handler, typeof(BasePage).FullName);
}
}
и это все! (как всегда не забудьте прописать модуль в web.config)
В поисках функциональности (и, возможно, элегантности) я обнаружил, что вместо использования IHttpModule
(я не хотел добавлять еще один класс) вы можете объявить BasePage
как таковой.
public abstract class BasePage : System.Web.UI.Page
{
public IInjectable FooProp {get;set;}
protected override OnPreInit(EventArgs e)
{
Spring.Context.Support.WebApplicationContext.Current
.ConfigureObject(this, typeof(BasePage).FullName);
base.OnPreInit(e);
}
}
и он работает как шарм, не требуя каких-либо дополнительных модулей и т. д.
К счастью, это работает и для пользовательских элементов управления (хотя и в другом событии жизненного цикла, поскольку OnPreInit не существует для пользовательских элементов управления):
public abstract class BaseControl : System.Web.UI.UserControl
{
public IInjectable FooProp {get;set;}
protected override OnInit(EventArgs e)
{
Spring.Context.Support.WebApplicationContext.Current
.ConfigureObject(this, typeof(BaseControl).FullName);
base.OnInit(e);
}
}
Спасибо за просмотр!