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();
        });
    }
}