如何使用DryIoc.Container解析实现接口的特定类型的实例(在运行时已知)

时间:2016-08-17 02:17:09

标签: c# ioc-container dryioc

标题可能具有误导性,但基本上我希望DryIoc.Container解析类型(类的类型)的特定实现实现界面)在运行时相同界面多个实现)被注册。 我无法使用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}}

我知道我可以获取所有接口的已注册实现,并过滤具有我想要的实现的(使用类似于此响应的代码{{3}由DryIoc的维护者提供,但是当我要求它时,我无法找到让容器解决它的方法!

1 个答案:

答案 0 :(得分:2)

DryIoc, Spring.Net's GetObjectsOfType equivalent?的答案几乎就在现场。

在此处重复选项:

使用实现类型作为服务密钥

container.Register<IService, ServiceImpl_1>(serviceKey: typeof(ServiceImpl_1));
container.Resolve<IService>(serviceKey: typeof(ServiceImpl_1));

使用RegisterMany

这将作为服务类型注册所有已实现的公共类型,包括实现类型本身:

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());
        }
    }
}

Live example

手动从容器注册中选择

找到具有给定实现类型的已注册工厂,并获取用于注册的实际默认密钥。使用密钥解决:

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);
        }
    }
}

Live example