我研究过 Ninject、StructureMap 和其他依赖注入和服务定位器框架,但这个问题更多的是关于了解它是如何工作的以及什么可以做得更好。更重要的是,我无意于查看框架的依赖注入源代码,而是了解它在实践/代码中从头到尾是如何实现的。
下面的代码适用于一个小型内部项目,因此让我开始吧。
这是我将域模型返回到我的控制器的界面。我决定,由于项目的规模(小),控制器的单一接口是可以接受的。
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);
}
每个控制器都继承自DIBaseController
所以我不必为每个控制器创建私有成员。
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)
{
}
}
创建了我自己的控制器工厂,它允许我将 ModelFactory 注入控制器中。
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 thisnamespace = 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;
}
}
最后添加代码将 Concreate 类注入到工厂中以注入到创建的控制器中。
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new DIControllerFactory(new LinqSqlModelFactory()));
}
我唯一没有探索过的领域(而且我认为我目前对此不感兴趣)是创建一个web.config
部分动态创建ModelFactory
。这可行,但我感兴趣的是我是否完全错过了机会,是否接近,或者我是否恰到好处?