Is it possible to have multiple dependency resolvers in ASP.NET MVC 3?

前端 未结 2 1920
悲哀的现实
悲哀的现实 2021-02-10 09:00

Is it possible to have more than one dependency resolver in ASP.NET MVC 3 (similar to the case of ModelBinders and Providers)?

相关标签:
2条回答
  • 2021-02-10 09:28

    Is it possible to have more than one dependency resolver in ASP.NET MVC 3 (similar to the case of ModelBinders and Providers)?

    No, this isn't possible. The DependencyResolver.Current is a static property that could be assigned only one resolver. This being said having more than one dependency resolver in an application hardly makes any sense. The idea is that all your dependencies are managed by a dependency injection framework such as Unity, Ninject or StructureMap. You would then have a custom dependency resolver wrapping your DI framework of choice that will be used by ASP.NET MVC to inject dependencies in various objects of the execution pipeline.

    You are comparing it with model binders in your question but this comparison is unfair because a model binder is related to a specific type that it is designed to bind. Basically you could have many custom model binders for multiple view models.

    You also seem to have mentioned some providers in your question but unfortunately you haven't beeen very specific so it's a bit harder to comment on this one.

    0 讨论(0)
  • 2021-02-10 09:35

    There is one scenario that I could think of where having multiple 'containers' or 'resolvers' is useful and that is multi-tenancy. With multi tenancy you run multiple customers (organizations, with their own set of users) in the same web application, and dynamically switch based on the login, request info, or domain info.

    Still, DependencyResolver.Current is -as Darin noted- static, so there's nothing you can (or should do about this). However, you could hide multiple containers behind a single IDependencyResolver abstraction and return an implementation based on some criteria. It might look like this:

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

    The following code snippet shows the usage of this 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>();
    }
    
    0 讨论(0)
提交回复
热议问题