c# 基于路由参数的 MVC 依赖注入
c# MVC dependency injection based on route param
我想做的是使用 NInject 和路由参数实例化服务。
我有这样的东西:
DAL
public interface IDALContract
{
object GetById(int id);
}
public class DALPeopleContract : IDALContract
{
public object GetById(int id)
{
//get person
return null;
}
}
public class DALAnimalsContract : IDALContract
{
public object GetById(int id)
{
//get animal
return null;
}
}
public static class DALContractFactory
{
public static IDALContract GetContract(int discriminator)
{
switch(discriminator)
{
case 1: return new DALPeopleContract();
case 2: return new DALAnimalsContract();
default: throw new NotSupportedException();
}
}
}
业务层
public interface IMyService
{
object GetById(int id);
}
public class MyService : IMyService
{
private IDALContract _contract;
public MyService(int discriminator)
{
_contract = DALContractFactory.GetContract(discriminator)
}
public object GetById(int id)
{
return _contract.GetById(id);
}
}
控制器
public class MyController
{
private IMyService _myService;
public MyController()
{
//how do I get the discriminator here? (the discriminator should be a route param)
IParameter param = new Parameter("MyParam", discriminator, true);
_myService = NInjectKernel.TryGet<IMyService>(param);
}
ActionResult Index(id)
{
_myService.GetById(id);
return View(model);
}
}
所以我遇到的问题是如何获取参数,或者是否有更好的方法。基本上我想做的是让一个控制器为不同的模型处理相同的操作,但我遇到了数据访问层 (DAL) 的问题。
获取 OnActionExecuting 的值并在那里实例化服务是个好主意吗?
我找到了一个干净的(在我看来)解决我的问题的方法。
所以现在我有一个相当简单的方法来处理相关的简单操作 类。
我用一些 NInject 绑定替换了 DALContractFactory。我为我的控制器定义了一个自定义路由,它需要一个 "type",它在我的控制器上的 OnActionExecuting 中读取。
对于模型,我有一个工厂定义和一个自定义映射器(我没有在这里 post编辑它们,因为它们与问题无关)。如果有人感兴趣,我可以 post 使用这种方法的示例 sln。
所以现在我有类似的东西:
DAL
public interface IDALContract
{
object GetById(int id);
}
public class DALPeopleContract : IDALContract
{
public object GetById(int id)
{
//get person
return null;
}
}
public class DALAnimalsContract : IDALContract
{
public object GetById(int id)
{
//get animal
return null;
}
}
业务层
public enum Discriminator
{
Animal,
Person
}
public interface IMyService
{
object GetById(int id);
}
public class MyService : IMyService
{
private IDALContract _contract;
public MyService(IDALContract contract)
{
_contract = contract;
}
public object GetById(int id)
{
return _contract.GetById(id);
}
}
控制器
public class MyController : Controller
{
private IMyService _myService;
protected override void OnActionExecuting(ActionExecutingContext ctx)
{
base.OnActionExecuting(ctx);
int type;
var routeValue = ControllerContext.RouteData.Values["type"];
Discriminator type;
if(!Enum.TryParse<Discriminator>(routeValue.ToString(), out type))
{
//set a default value
type = Discriminator.Animal;
}
_myService = NInjectKernel.Instance.GetService<IMyService>("type", type);
}
public ActionResult Index(id)
{
_myService.GetById(id);
return View(model);
}
}
NInject配置
public class NInjectKernel
{
private readonly IKernel _kernel;
private NInjectKernel()
{
_kernel = new StandardKernel();
}
private static volatile Irr2NInjectKernel _instance;
private static readonly object SyncRoot = new object();
public static Irr2NInjectKernel Instance
{
get
{
if (_instance == null)
{
lock (SyncRoot)
{
if (_instance == null)
{
var temp = new Irr2NInjectKernel();
temp.BindAllDependencies();
_instance = temp;
}
}
}
return _instance;
}
}
private void BindAllDependencies()
{
_kernel.Bind<IMyService>().To<MyService>();
_kernel.Bind<IDALContract>().ToMethod(x =>
{
IParameter parameter = x.Parameters.SingleOrDefault(p => p.Name == "type");
if (parameter != null)
{
var recordType = (Discriminator)parameter.GetValue(x, x.Request.Target);
switch (recordType)
{
case RecordType.Animal:
return new DALAnimalsContract();
case RecordType.Person:
return new DALPeopleContract();
default:
throw new NotSupportedException("DQS type is not suppported.");
}
}
throw new NotSupportedException();
});
}
}
我想做的是使用 NInject 和路由参数实例化服务。
我有这样的东西:
DAL
public interface IDALContract
{
object GetById(int id);
}
public class DALPeopleContract : IDALContract
{
public object GetById(int id)
{
//get person
return null;
}
}
public class DALAnimalsContract : IDALContract
{
public object GetById(int id)
{
//get animal
return null;
}
}
public static class DALContractFactory
{
public static IDALContract GetContract(int discriminator)
{
switch(discriminator)
{
case 1: return new DALPeopleContract();
case 2: return new DALAnimalsContract();
default: throw new NotSupportedException();
}
}
}
业务层
public interface IMyService
{
object GetById(int id);
}
public class MyService : IMyService
{
private IDALContract _contract;
public MyService(int discriminator)
{
_contract = DALContractFactory.GetContract(discriminator)
}
public object GetById(int id)
{
return _contract.GetById(id);
}
}
控制器
public class MyController
{
private IMyService _myService;
public MyController()
{
//how do I get the discriminator here? (the discriminator should be a route param)
IParameter param = new Parameter("MyParam", discriminator, true);
_myService = NInjectKernel.TryGet<IMyService>(param);
}
ActionResult Index(id)
{
_myService.GetById(id);
return View(model);
}
}
所以我遇到的问题是如何获取参数,或者是否有更好的方法。基本上我想做的是让一个控制器为不同的模型处理相同的操作,但我遇到了数据访问层 (DAL) 的问题。
获取 OnActionExecuting 的值并在那里实例化服务是个好主意吗?
我找到了一个干净的(在我看来)解决我的问题的方法。
所以现在我有一个相当简单的方法来处理相关的简单操作 类。
我用一些 NInject 绑定替换了 DALContractFactory。我为我的控制器定义了一个自定义路由,它需要一个 "type",它在我的控制器上的 OnActionExecuting 中读取。
对于模型,我有一个工厂定义和一个自定义映射器(我没有在这里 post编辑它们,因为它们与问题无关)。如果有人感兴趣,我可以 post 使用这种方法的示例 sln。
所以现在我有类似的东西:
DAL
public interface IDALContract
{
object GetById(int id);
}
public class DALPeopleContract : IDALContract
{
public object GetById(int id)
{
//get person
return null;
}
}
public class DALAnimalsContract : IDALContract
{
public object GetById(int id)
{
//get animal
return null;
}
}
业务层
public enum Discriminator
{
Animal,
Person
}
public interface IMyService
{
object GetById(int id);
}
public class MyService : IMyService
{
private IDALContract _contract;
public MyService(IDALContract contract)
{
_contract = contract;
}
public object GetById(int id)
{
return _contract.GetById(id);
}
}
控制器
public class MyController : Controller
{
private IMyService _myService;
protected override void OnActionExecuting(ActionExecutingContext ctx)
{
base.OnActionExecuting(ctx);
int type;
var routeValue = ControllerContext.RouteData.Values["type"];
Discriminator type;
if(!Enum.TryParse<Discriminator>(routeValue.ToString(), out type))
{
//set a default value
type = Discriminator.Animal;
}
_myService = NInjectKernel.Instance.GetService<IMyService>("type", type);
}
public ActionResult Index(id)
{
_myService.GetById(id);
return View(model);
}
}
NInject配置
public class NInjectKernel
{
private readonly IKernel _kernel;
private NInjectKernel()
{
_kernel = new StandardKernel();
}
private static volatile Irr2NInjectKernel _instance;
private static readonly object SyncRoot = new object();
public static Irr2NInjectKernel Instance
{
get
{
if (_instance == null)
{
lock (SyncRoot)
{
if (_instance == null)
{
var temp = new Irr2NInjectKernel();
temp.BindAllDependencies();
_instance = temp;
}
}
}
return _instance;
}
}
private void BindAllDependencies()
{
_kernel.Bind<IMyService>().To<MyService>();
_kernel.Bind<IDALContract>().ToMethod(x =>
{
IParameter parameter = x.Parameters.SingleOrDefault(p => p.Name == "type");
if (parameter != null)
{
var recordType = (Discriminator)parameter.GetValue(x, x.Request.Target);
switch (recordType)
{
case RecordType.Animal:
return new DALAnimalsContract();
case RecordType.Person:
return new DALPeopleContract();
default:
throw new NotSupportedException("DQS type is not suppported.");
}
}
throw new NotSupportedException();
});
}
}