How to configure simple injector container and lifestylse in a MVC web app with WebAPI, WCF, SignalR and Background Task

前端 未结 2 387
逝去的感伤
逝去的感伤 2021-02-05 20:38

The simple injector documentation provides great examples on how to setup the container for WebRequest, Web API, WCF, ... but the examples are specific to one technology/lifest

2条回答
  •  夕颜
    夕颜 (楼主)
    2021-02-05 20:55

    I have to say, I stumble on a similar scenario some time ago, I ended up by sharing my configuration over my web API and signalR, but you need to implement a custom lifestyle for signalR since it's not based on web request.

    specially in signalR you'll find some issues handling per-web-request dependencies in a Hub some of them are going to be null like httpContext.Current among others.

    The solution:

    You need a hybrid lifestyle between WebRequestLifestlye and either Lifestyle.Transient, Lifestyle.Singleton, or LifetimeScopeLifestyle. I ended up I finished using the decorator pattern, you may read this post and this other post.

    my decorator

    public class CommandLifetimeScopeDecorator : ICommandHandler
        {
            private readonly Func> _handlerFactory;
            private readonly Container _container;
    
            public CommandLifetimeScopeDecorator(
            Func> handlerFactory, Container container)
            {
                _handlerFactory = handlerFactory;
                _container = container;
            }
    
            public void Handle(T command)
            {
                using (_container.BeginLifetimeScope())
                {
                    var handler = _handlerFactory(); // resolve scoped dependencies
                    handler.Handle(command);
                }
            }
    
        }
    
        public interface ICommandHandler
        {
            void Handle(T command);
        }
    

    I managed the dependencies using a hub activator for signalR

    public class MyHubActivator : IHubActivator
        {
            private readonly Container _container;
    
            public MyHubActivator(Container container)
            {
                _container = container;
            }
    
            public IHub Create(HubDescriptor descriptor)
            {
                return _container.GetInstance(descriptor.HubType) as IHub;
            }
        }
    

    a composite root file which is where you are going to handle your dependencies

    public CompositRoot(Container container)
    {
        _container = container;
    }
    public container Configure()
    {
       // _container.Registerall container dependencies
       return _container;
    }
    

    then share your composite root configuration when you are bootstrapping your app

    var compositRoot = new CompositRoot(simpleInjector.Container); //simple injector instance
    compositRoot.Configure();
    

    For signalR

    GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new MyHubActivator(compositRoot));
    

    and you may reuse your configuration among other projects!

    my two cents hope that helps!

提交回复
热议问题