Consider this abstract class
public abstract class Foo
{
public Injectable Prop {get;set;}
}
i have an application that i want to enhance and simultaneously refactor for simplicity.
I have over 100 classes that call some same stuff (e.g Class Injectable) and i am thinking that this behaviour can be abstracted and set to a base class, and everybody will inherit from this base class so as to remove copy/paste code.
However, i want to avoid copy/paste code in the spring configuration file by defining an Injectable object and then define a child object foreach and every class that inherits from Foo.
I am looking for a way to set the abstract class’s properties and then all child elements to automatically get them via configuration. I want to avoid to make the abstract class like this:
public abstract class Foo
{
public Injectable Prop
{
get { return (Injectable)ContextRegistry.GetContext()["Injectable"]; }
}
}
thanks for any suggestions
EDIT:
to make things a bit more complicated the child classes are ASP.NET pages, so i have limited control as to how they are generated.
Currently i’m employing the above mentioned code where the abstract class makes a reference to a DI created object with Id “Injectable”. I would like to avoid flying strings
UPDATE (With solution)
Consider:
Classes
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();
}
}
spring cfg
…
<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>
and the effect will be for each inheritor of BasePage will have the FooProp property injected with what i configured.
it matters little if this can be achieved with some kind of convention binding but i do not want use strings and using DI references from inside my code.
2nd UPDATE AND SOLUTION
thanks to tobsen and Erich Eichinger the solution was found:
Firstly, this is not supported natively, but the solution is not very ugly nor breaks DI pattern norms in a bad way
Now, all the spring configuration required is given above (in the update)
Erich’s solution is this, make an IHttpModule like so:
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);
}
}
and that’s it!
(don’t forget to register the module in web.config as always)
In search of functionality (and perhaps elegance) i found that instead of using the IHttpModule (i did’t want to add yet another class) you can declare the BasePage as such
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);
}
}
and it works like a charm without requiring any added modules etc.
Gladly this works on UserControls as well (albeit in a different event in the lifecycle since OnPreInit does not exist for usercontrols):
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);
}
}
thanks for watching!
sorry I have only limited time atm, plz ping me if the description below should be too short/abstract
First, there is no such functionality yet available. But with a few lines of code you can do this on your own.
In general below I will be pursuing the idea of mapping a particular class onto an object-definition to be used for configuring the instance. Something along the lines of
Here’s the outline of a solution:
Since your problem is ASP.NET WebForms-related, an HttpModule is a good starting point to hook into creating and configuring .aspx pages.
The idea is to write your own IHttpModule that performs the page configuration right before it gets executed. Basically all you need is
and configure your module according to 22.4.2. Injecting dependencies into custom HTTP modules.
hth,
Erich