ASP.NET MVC 3中是否可以有多个依赖项解析器?

Gui*_*rez 3 dependency-injection asp.net-mvc-3

ASP.NET MVC 3中是否可以有多个依赖项解析程序(类似于ModelBinder和Providers的情况)?

Ste*_*ven 6

有一种情况我可以想到有多个"容器"或"解析器"是有用的,这是多租户.通过多租户,您可以在同一个Web应用程序中运行多个客户(组织,拥有自己的一组用户),并根据登录,请求信息或域信息动态切换.

仍然DependencyResolver.Current是 - 达林注意到 - 静止,所以没有什么可以(或者应该做的).但是,您可以在单个IDependencyResolver抽象后面隐藏多个容器,并根据某些条件返回实现.它可能看起来像这样:

public class MultiTenantDependencyResolver 
    : IDependencyResolver
{
    Func<int> tenantIdSelector,;
    IDictionary<int, IDependencyResolver> tenantResolvers;

    public MultiTenantDependencyResolver(
        Func<int> tenantIdSelector,
        IDictionary<int, IDependencyResolver> tenantResolvers)
    {
        this.tenantIdSelector = tenantIdSelector;
        this.tenantResolvers= tenantResolvers;
    }

    private IDependencyResolver CurrentResolver
    { 
        get { return this.tenantResolvers[tenantIdSelector()]; }
    }

    public object GetService(Type serviceType)
    {
        return this.CurrentResolver.GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.CurrentResolver.GetAllInstances(serviceType);
    }
}
Run Code Online (Sandbox Code Playgroud)

以下代码段显示了此用法MultiTenantDependencyResolver:

var tenantResolvers = new Dictionary<int, IDependencyResolver>
{
    { Tenants.AbcId, BuildResolver(RegisterForTenantAbc) },
    { Tenants.KlmId, BuildResolver(RegisterForTenantKlm) },
    { Tenants.XyzId, BuildResolver(RegisterForTenantXyz) },
};

var multiTenantResolver = new MultiTenantResolver(
    () => GetTenantIdFromUrl(), tenantResolvers);

DependencyResolver.SetResolver(multiTenantResolver);


private static int GetTenantIdFromUrl()
{
    // TODO: return tenant id
}

private static IDependencyResolver BuildResolver(
    Action<IKernel> tenantSpecificRegistrations)
{
    var kernel = new Kernel();

    // TODO: Tenant agnostic registrations. For instance
    kernel.Bind<ITimeProvider>().To<SystemTimeProvider>();

    tenantSpecificRegistrations(kernel);

    return new NinjectDependencyResolver(kernel);
}

private static void RegisterForTenantAbc(IKernel kernel)
{
    // TODO: regisrations for ABC tenant. For instance
    kernel.Bind<ILogger>().To<AbcTenantLogger>();
}
Run Code Online (Sandbox Code Playgroud)