如何解析使用 DryIoc.Container 实现接口的特定类型(在运行时已知)的实例
how to resolve an instance of a specific type (known at runtime) that implements an interface using DryIoc.Container
标题可能具有误导性,但基本上我希望 DryIoc.Container
解析 特定 接口的实现,其 type(class 实现接口的类型)在 运行时 给出(多个实现 相同的接口 已注册)。
我不能使用 serviceKey
来识别 实现 因为 解决 实现的代码预计会做类似的事情: container.Resolve<IService>(*** here specify the runtime type of the implementation ***)
来获得我们想要的实现(实现的类型是通过我们在运行时读取的配置获取的)。
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());
}
}
}
`
上面的代码抛出:
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}}
我知道我可以获得接口的所有已注册实现并过滤具有我想要的实现的实现(使用代码类似于 DryIoc 的维护者的回应 ),但是当我要求容器解决它时,我无法找到一种方法来解决它!
的答案几乎是当场的。
在这里重复选项:
使用实现类型作为服务密钥
container.Register<IService, ServiceImpl_1>(serviceKey: typeof(ServiceImpl_1));
container.Resolve<IService>(serviceKey: typeof(ServiceImpl_1));
使用RegisterMany
这会将所有已实现的 public 类型注册为服务类型,包括实现类型本身:
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());
}
}
}
Select 从容器手动注册
查找具有给定实现类型的注册工厂,并获取用于注册的实际默认密钥。使用密钥解决:
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_2
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);
}
}
}
标题可能具有误导性,但基本上我希望 DryIoc.Container
解析 特定 接口的实现,其 type(class 实现接口的类型)在 运行时 给出(多个实现 相同的接口 已注册)。
我不能使用 serviceKey
来识别 实现 因为 解决 实现的代码预计会做类似的事情: container.Resolve<IService>(*** here specify the runtime type of the implementation ***)
来获得我们想要的实现(实现的类型是通过我们在运行时读取的配置获取的)。
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());
}
}
}
`
上面的代码抛出:
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}}
我知道我可以获得接口的所有已注册实现并过滤具有我想要的实现的实现(使用代码类似于 DryIoc 的维护者的回应
在这里重复选项:
使用实现类型作为服务密钥
container.Register<IService, ServiceImpl_1>(serviceKey: typeof(ServiceImpl_1));
container.Resolve<IService>(serviceKey: typeof(ServiceImpl_1));
使用RegisterMany
这会将所有已实现的 public 类型注册为服务类型,包括实现类型本身:
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());
}
}
}
Select 从容器手动注册
查找具有给定实现类型的注册工厂,并获取用于注册的实际默认密钥。使用密钥解决:
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_2
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);
}
}
}