How to set up IoC when a key class needs Session (or other context-specific variable)

后端 未结 1 1114
失恋的感觉
失恋的感觉 2020-12-16 02:49

I am trying to figure out how to use IoC in situations where the dependent classes can change based on some variable in the application (in this case, Session state). For e

相关标签:
1条回答
  • 2020-12-16 03:31

    How the Repository instance is created, as well as its lifetime, is of no concern of the Controller.

    When you register components in the container, you should specify the lifetime of the component. Depending on your implementation, you may simply choose to set the lifefime of the Repository to follow the session.

    In any case you could use a factory to create the repository from the session, but do this from outside the Controller.

    You definitely need to get rid of the default constructor.


    Off the top of my head I can't remember how to do this in Unity or StructureMap, so here's a Castle Windsor example.

    Define an Abstract Factory:

    public interface IRepositoryFactory
    {
        Repository Create();
    }
    

    and an implementation

    public class MyRepositoryFactory : IRepositoryFactory
    {
        private readonly HttpContextBase httpContext;
    
        public MyRepositoryFactory(HttpContextBase httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }
    
            this.httpContext = httpContext;
        }
    
        #region IRepositoryFactory Members
    
        public Repository Create()
        {
            // return Repository created from this.httpContext
        }
    
        #endregion
    }
    

    Now register all the stuff

    container.AddFacility<FactorySupportFacility>();
    container.Register(Component.For<IRepositoryFactory>()
        .ImplementedBy<MyRepositoryFactory>()
        .LifeStyle.PerWebRequest);
    container.Register(Component.For<Repository>()
        .UsingFactory((IRepositoryFactory f) => f.Create())
        .LifeStyle.PerWebRequest);
    

    Here I've used the PerWebRequest lifestyle, but if you want to optimize you might want to create a custom PerWebSession lifestyle. This is not too hard to do in Castle, but I can't remember how hard it is in other DI Containers.

    You will also need to register HttpContextBase, since MyRepositoryFactory depends on it.

    0 讨论(0)
提交回复
热议问题