3

I need to have the resolution of a dependency for my services to be based off the value of an HTTP header in the incoming request.

I've tried registering a factory method like so:

container.Register(c => GetDependencyForRequest(c.Resolve<IHttpRequest>()));

and also I've tried:

container.Register(c => GetDependencyForRequest(c.Resolve<IRequestContext>()));

However, both throw ResolutionExceptions.

I'd prefer not to have to saddle my Services with deciding which implementation to use. I'd just like them to have an IDependency in their constructor and let the container resolve it.

Is there some way to do this? Or is there another way to go about this?

Scott
  • 21,211
  • 8
  • 65
  • 72
rossipedia
  • 56,800
  • 10
  • 90
  • 93

2 Answers2

2

I'm not sure if there is a way to do it via an IoC container. A possible solution would be to create your own subclass of Service that can 'new up' your IDependency in its constructor based on the Http Header. Below is some psuedocode to give you an idea. Hope this helps.

public abstract class MyServiceBase : Service
{
    private Dictionary<string, Func<IDependency>> Dependencies = new Dictionary<string, Func<Dependency>>()
                                                                    {
                                                                        {"header1", () => new Dependency()},
                                                                        {"header2", () => new Dependency()}
                                                                    };

    public IDependency Dependency { get; set; }

    protected MyServiceBase()
    {
        this.Dependency = this.Dependencies[this.RequestContext.GetHeader("headerName")]();
    }
}
paaschpa
  • 4,816
  • 11
  • 15
1

The answer was much simpler than I thought:

container.Register(c => FindDependencyForRequest(HttpContext.Current.ToRequestContext()));
rossipedia
  • 56,800
  • 10
  • 90
  • 93
  • If you're using [ServiceStack's built-in Funq IOC](https://github.com/ServiceStack/ServiceStack/wiki/The-IoC-container) you'd want to not make it a singleton by specifying **ReuseScope.None** i.e. `container.Register(c => new FindDependencyForRequest(HttpContext.Current.ToRequestContext())).ReusedWithin(ReuseScope.None);` – mythz Feb 15 '13 at 02:20
  • I was under the impression that using the `Func` overload of `Container.Register` caused the provided factory to be called each resolution, effectively making the reuse scope transient. Is the `ReusedWithin(ReuseScope.None)` actually necessary? – rossipedia Feb 15 '13 at 07:32
  • 1
    Not sure why you would assume that, all the docs says it's singleton by default and you can use `.ReusedWithin()` to change the lifetime. [Here are some tests that shows Funq's default behavior.](https://github.com/ServiceStack/ServiceStack/commit/b7ec3fae3db9fa6ccccd19dcc39ee3167017c8d2) – mythz Feb 15 '13 at 08:04
  • That's my bad. I must have missed that. I was assuming that behavior as most other IoC containers use Transient lifetime as default behavior. – rossipedia Feb 15 '13 at 16:06