-
Notifications
You must be signed in to change notification settings - Fork 0
The IoC container
ServiceStack uses a slightly modified version of Funq - a very fast IoC container. Funq is also used internally for creating new service instances because of the high performance. Of course there's the possibility to use another IoC container as a dependency repository where Funq can try to access registered type which were not registered in Funq itself. So you aren't forced to use Funq as your IoC container.
So you can resolve any types from your custom IoC container except of:
- Services
- Filter attributes (are executed before a service gets called)
- Validators (validates a request DTO before the service gets called)
These are main components of ServiceStack which have very high performance requirements, so they need to be heavily cached. You'll read more about filter attributes and validators in the next documentation pages.
Funq has the option to register Func<TType>
as factories. These functions can be anything which has the correct signature and are not limited to delegates of the form
c=> new MyType()
but could be
c => CreateAndInitialzeMyType(c.Resolve<IOne>(), c.Resolve<ITwo>)
The first is using the type-safe generic Register methods. There are versions for both named and un-named registrations. Both take as a parameter, a delegate which takes a Container as its single parameter and returns an instance of the type.
public IRegistration Register<TType>(Func<Container, TType> func)
public IRegistration Register<TType>(string name, Func<Container, TType>func)
The second method is using the type-safe generic register instance methods. There are versions for both named and un-named registrations. Both take as a parameter, an instance of the type.
public void Register<TType>(TType instance)
public void Register<TType>(string name, TType instance)
Note: When using the methods above, the properties and the constructor of the registered type aren't auto-wired (ie the properties and the constructor are not injected). You would need to do that manually like that:
container.Register<T>(c => new Foo(c.Resolve<Some>(), c.Resolve<Other>(), c.Resolve<Dependencies>());
public IRegistration<T> RegisterAutoWired<T>();
public IRegistration<TAs> RegisterAutoWiredAs<T, TAs>() where T : TAs;
If you are using one of these two methods, the constructor and the properties of the registered type will be injected, too.
By default all dependencies registered with Funq are singleton. If you want that a new dependency is created everytime (ie transient scope), you need to define the reuse scope manually:
container.Register(c => new TodoRepository()).ReusedWithin(ReuseScope.None);
public interface IContainerAdapter
{
T Resolve<T>();
T TryResolve<T>();
}
If you've registered a dependency repository (ie IContainerAdapter
), the services itself are created by Funq, but the properties of the services are injected by your custom dependency repository (Windsor, Ninject, ...). So for every property on a service, the method TryResolve<T>
is called. How the IContainerAdapter
creates the type of the requested instance doesn't matter. Like for services, it work's the same with filter attributes and validators.
Of course custom attributes (like [Ignore]
from Ninject which notify the Ninject container to not resolve the marked property) or something similar of your custom IoC container aren't noted in the services, because Funq is the one which creates a service. But for all types which are resolved by calling IContainerAdapter
the behavior of your IoC container isn't changed.
So here are some example how to use some popular IoC containers side-by-side with Funq. Of course you aren't limited to the these IoC containers, you can use any IoC container of your choice.
public class NinjectIocAdapter : IContainerAdapter
{
private readonly IKernel kernel;
public NinjectIocAdapter(IKernel kernel)
{
this.kernel = kernel;
}
public T Resolve<T>()
{
return this.kernel.Get<T>();
}
public T TryResolve<T>()
{
return this.kernel.TryGet<T>();
}
}
Then in the AppHost
Configure(Container container)
method you need to enable this adapter:
//Create Ninject IoC container
IKernel kernel = new StandardKernel();
//Now register all depedencies to your custom IoC container
//...
//Register Ninject IoC container, so ServiceStack can use it
container.Adapter = new NinjectIocAdapter(kernel);
public class StructureMapContainerAdapter : IContainerAdapter
{
public T TryResolve<T>()
{
return ObjectFactory.TryGetInstance<T>();
}
public T Resolve<T>()
{
return ObjectFactory.TryGetInstance<T>();
}
}
In AppHost
Configure
:
//Configure User Defined REST Paths
container.Adapter = new StructureMapContainerAdapter();
//Register your dependencies
ObjectFactory.Inject(typeof(IFoo), new Foo());
Note: Due a behavior of StructureMap, you need your
AppHost
declare asinternal
, eg:internal class AppHost : AppHostBase
public class WindsorContainerAdapter : IContainerAdapter, IDisposable
{
private readonly IWindsorContainer _container;
public WindsorContainerAdapter()
{
_container = new WindsorContainer().Install(FromAssembly.InThisApplication(),
FromAssembly.InDirectory(new ApplicationAssemblyFilter()));
}
public T TryResolve<T>()
{
return Resolve<T>();
}
public T Resolve<T>()
{
return _container.Resolve<T>();
}
public void Dispose()
{
_container.Dispose();
}
}
- Why ServiceStack?
- What is a message based web service?
- Advantages of message based web services
- Why remote services should use separate DTOs
- Getting Started
- Reference
- Clients
- Formats
- View Engines 4. Razor & Markdown Razor
- Hosts
- Advanced
- Configuration options
- Access HTTP specific features in services
- Logging
- Serialization/deserialization
- Request/response filters
- Filter attributes
- Concurrency Model
- Built-in caching options
- Built-in profiling
- Messaging and Redis
- Form Hijacking Prevention
- Auto-Mapping
- HTTP Utils
- Virtual File System
- Config API
- Physical Project Structure
- Modularizing Services
- Plugins
- Tests
- Other Languages
- Use Cases
- Performance
- How To
- Future