I've looked at Ninject, StructureMap and Other Dependency Injection and Service Locator frameworks, but this question is more about learning how it works and what can be better. More to the point, I’m not interesting in looking at a Framework’s source code for Dependency Injection, but understanding how it’s achieved from beginning to end in practice/code.
The code below is for a small internal project, so with that in mind let me begin.
Here is my interface for returning Domain Models to my controllers. I've decided that due to the size of the project (small), a single interface for Controllers was acceptable.
interface IModelFactory
{
IEnumerable<User> GetUsers();
User GetUser(Guid UserID);
bool Add(User User);
bool Delete(User User);
bool Update(User User);
IEnumerable<Car> GetCars();
Car GetCar(Guid CarID);
bool Add(Car Car);
bool Delete(Car Car);
bool Update(Car Car);
}
Each controller has inherits from DIBaseController
so I didn't have to create private members for every controller.
public abstract class DIBaseController : Controller
{
protected IModelFactory ModelFactory { get; set; }
public DIBaseController(IModelFactory ModelFactory)
{
this.ModelFactory = ModelFactory;
}
}
public class HomeController : DIBaseController
{
public HomeController (IModelFactory ModelFactory)
: base(ModelFactory)
{
}
}
Created my own Controller Factory that allows me to inject my ModelFactory into Controllers.
internal class DIControllerFactory : DefaultControllerFactory
{
private IModelFactory _ModelFactory;
internal DIControllerFactory(IModelFactory ModelFactory)
{
this._ModelFactory = ModelFactory;
}
public override IController CreateController(RequestContext requestContext, string controllerName)
{
IController result = null;
string thisnam开发者_运维知识库espace = this.GetType().Namespace;
//This could be improved I bet.
Type controller = Type.GetType(thisnamespace.Substring(0, thisnamespace.IndexOf('.')) + ".Controllers." + controllerName + "Controller");
if (controller != null
&& controller.IsSubclassOf(typeof(DIBaseController)))
{
result = (IController)Activator.CreateInstance(controller, new object[] { this._ModelFactory });
}
else
{
result = base.CreateController(requestContext, controllerName);
}
return result;
}
}
And finally added the code to Inject the Concreate class into the Factory to inject into created Controllers.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new DIControllerFactory(new LinqSqlModelFactory()));
}
The only area I haven't explored (and I don't think I'm interested in at the moment) is to create a web.config
section to dynamically create the ModelFactory
. This works, but I'm interested if I've completely missed the boat, come close, or if I'm spot on?
Instead of overriding CreateController use
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
It gives you the controller type and the first part of your implementation is obsolete.
The next point you have to improve is that you analyze the parameters of the constructor and pass an instance of those parameters which are created using some configuration instead of guessing that there is exactly one parameter IModelFactory.
精彩评论