the title is, maybe, misleading but basically I want the DryIoc.Container
to resolve a specific implementation of an interface whose type (the type of the class the implements the interface) is given at runtime ( multiple implementations of the same interface are registered ).
I can't use serviceKey
to identify implementations because the code that resolves the implementation is expected to do something like : container.Resolve<IService>(*** here specify the runtime type of the implementation ***)
to get the implementation we want (the type of the implementation is acquired via a configuration we read at runtime).
using System;
using DryIoc;
namespace DryIoc_example
{
interface IService { }
class ServiceImpl_1 : IService { }
class ServiceImpl_2 : IService { }
class Program
{
static void Main(string[] args)
{
var container = new Container();
// register my implementations of IService
// this could be done at runtime using
// container.Register(typeof(IService), typeof(ServiceImpl_1));
container.Register<IService, ServiceImpl_1>();
container.Register<IService, ServiceImpl_2>();
// now, i want the container to resolve a specific
// implementation of IService ( ServiceImpl_2 in this case)
// this line doesn't work and throws
var myService = container.Resolve<IService>(typeof(ServiceImpl_2));
// this line is expected to print the type of ServiceImpl_2
Console.WriteLine(myService.GetType());
}
}
}
`
the code above throws :
Unable to resolve DryIoc_example.IService {RequiredServiceType=DryIoc_example.ServiceImpl_2}
Where CurrentScope: null
and ResolutionScope: null
and Found registrations:
DefaultKey.Of(0),{ID=20, ImplType=DryIoc_example.ServiceImpl_1}}
DefaultKey.Of(1),{ID=21, ImplType=DryIoc_example.ServiceImpl_2}}
I know I can get all the registered implementations for an interface and filtering the one that has the implementation I want (using code similar to this response https://stackoverflow.com/a/37069854/5767019 by the maintainer of DryIoc ), but I couldn't figure out a way to make the container resolve it when I ask it to !
The answer for DryIoc, Spring.Net's GetObjectsOfType equivalent? is pretty much on the spot.
Repeating the options here:
container.Register<IService, ServiceImpl_1>(serviceKey: typeof(ServiceImpl_1));
container.Resolve<IService>(serviceKey: typeof(ServiceImpl_1));
This will do registration with all implemented public types as service types, including implementation type itself:
using System;
using DryIoc;
namespace DryIoc_example
{
interface IService {}
class ServiceImpl_1 : IService {}
class ServiceImpl_2 : IService {}
public class Program
{
public static void Main()
{
var container = new Container();
container.RegisterMany<ServiceImpl_1>(nonPublicServiceTypes: true);
container.RegisterMany<ServiceImpl_2>(nonPublicServiceTypes: true);
var myService = container.Resolve<IService>(typeof(ServiceImpl_2));
// this line is expected to print the type of ServiceImpl_2
Console.WriteLine(myService.GetType());
}
}
}
Find the registered factory with given implementation type, and get the actual default key used for registration. Resolve using the key:
using System;
using System.Linq;
using DryIoc;
namespace DryIoc_example
{
public interface IService {}
class ServiceImpl_1 : IService {}
class ServiceImpl_2 : IService {}
public class Program
{
public static void Main()
{
var container = new Container();
container.Register<IService, ServiceImpl_1>();
container.Register<IService, ServiceImpl_2>();
var myService = container.TryResolveByImplementation<IService>(typeof(ServiceImpl_1));
// this line is expected to print the type of ServiceImpl_1
Console.WriteLine(myService.GetType());
}
}
public static class ContainerExtensions
{
public static TService TryResolveByImplementation<TService>(this IContainer container, Type implementationType)
{
var factory = container.GetAllServiceFactories(typeof(TService))
.FirstOrDefault(f => f.Value.ImplementationType == implementationType);
return factory != null
? container.Resolve<TService>(serviceKey: factory.Key)
: default(TService);
}
}
}