Search code examples
c#servicestackmef

Use MEF in ServiceStack services


I'm trying to use MEF as ContainerAdapter in ServiceStack (https://github.com/ServiceStack/ServiceStack/wiki/The-IoC-container).

I've made ContainerAdapter:

internal class MefIocAdapter : IContainerAdapter
{
    private readonly CompositionContainer _container;

    internal MefIocAdapter(CompositionContainer container)
    {
        _container = container;
    }

    public T TryResolve<T>()
    {
        return _container.GetExportedValue<T>();
    }

    public T Resolve<T>()
    {
        return _container.GetExportedValueOrDefault<T>();
    }
}

and registered it like so:

    public override void Configure(Container container)
    {
        container.Adapter = new MefIocAdapter(_mefContainer);
    }

After registering service by RegisterService(System.Type, String) function, I'm getting MEF's exception. It can't find exports:

ContractName    ServiceStack.Auth.IAuthSession
RequiredTypeIdentity    ServiceStack.Auth.IAuthSession

Am i misunderstood something?

Why does Funq asks adapter container to resolve internal ServiceStack's dependency?

Will funq use MEF to instantiate my services? (if not, is there something like service factory?)

P.S. When I delete container.Adapter assignment it works (but ofc my MEF dependencies are null).


Solution

  • When you register a Container Adapter you're telling ServiceStack to resolve all dependencies with the Adapter, it only searches ServiceStack's IOC if the dependency isn't found in your Adapter first.

    The issue here is that IAuthSession is an optional property dependency where your Adapter should return null if the dependency doesn't exist so ServiceStack can then check the dependency in Funq.

    In your adapter you've got it the wrong way round where Resolve<T> (used for resolving Constructor dependencies) returns the default value and TryResolve<T> throws an exception when it doesn't exist when it should return the default value. So I'd change your Adapter implementation to:

    public T TryResolve<T>()
    {
        return _container.GetExportedValueOrDefault<T>();
    }
    
    public T Resolve<T>()
    {
        return _container.GetExportedValue<T>();
    }