0

由于通用接口,我想解决一个开放的通用服务。我使用自动法。

每个具体服务仅适用于具体类。

我只能用单个generic param[see SingleOpenGenericResolveTest] 解决一项服务。是否有可能注册和解决许多服务T-params[参见MultiOpenGenericResolveTest]?

我只添加了一个具体类,IService但它可能是很多类T。(TRegion : Region, TRegion : BigRegion等...)

这是 NUnit 3 测试,或者您可以在此处下载我的解决方案:https ://www.dropbox.com/s/vqmdwb6hwmzgjrb/AutofacResolveTests.zip?dl=0

using System;
using NUnit.Framework;
using Autofac;
using System.Reflection;
using System.Linq;

namespace AutofacResolveTests
{
    public class Address<TCity, TRegion, TSomethingElse>
        where TCity : City<TRegion>, new()
        where TRegion : Region, new()
        where TSomethingElse : SomethingElse, new()
    {
        public int Id { get; set; }
        TCity City { get; set; }
        TRegion Region { get; set; }
        TSomethingElse SomethingElse { get; set; }
    }

    public class City<TRegion>
        where TRegion : Region, new()
    {
        public int Id { get; set; }
        TRegion Region { get; set; }
    }

    public class Region
    {
        public int Id { get; set; }
    }

    public class SomethingElse
    {
        public int Id { get; set; }
    }

    public interface IService<T> where T : class
    {
        void DoSomething(T entity);
    }

    public class AddressService<TAddress, TCity, TRegion, TSomethingElse> : IService<TAddress>
        where TAddress : Address<TCity, TRegion, TSomethingElse>
        where TCity : City<TRegion>, new()
        where TRegion : Region, new()
        where TSomethingElse : SomethingElse, new()
    {
        public void DoSomething(TAddress entity)
        {
            Console.WriteLine("Hello from address service");
        }
    }

    public class CityService<TCity, TRegion> : IService<TCity>
        where TCity : City<TRegion>, new()
        where TRegion : Region, new()
    {
        public void DoSomething(TCity entity)
        {
            Console.WriteLine("Hello from city service");
        }
    }

    public class RegionService<TRegion> : IService<TRegion>
        where TRegion : Region
    {
        public void DoSomething(TRegion entity)
        {
            Console.WriteLine("Hello from region service");
        }
    }

    [TestFixture]
    public class OpenGenericResolveTests
    {
        IContainer _ioc;

        [SetUp]
        public void Setup()
        {
            var container = new ContainerBuilder();
        //manual types registration - works
        /*
        container.RegisterType(typeof(CityService<City<Region>, Region>)).As(typeof(IService<City<Region>>)).AsImplementedInterfaces();
        container.RegisterType(typeof(AddressService<
            Address<City<Region>, Region, SomethingElse>, City<Region>, Region, SomethingElse
            >))
            .As(typeof(IService<
            Address<City<Region>, Region, SomethingElse>
            >)).AsImplementedInterfaces();
        */

            var type = typeof(IService<>);
            //just get all services which implements IService
            var generics = type.Assembly.GetTypes().Where(x =>
            !x.IsInterface
            && x.Name.Contains("Service")
            && x.IsGenericType
            && x.GetInterfaces().Any(i => i.GetGenericTypeDefinition() == type)
            );

            foreach (var svcType in generics)
            {
                container.RegisterGeneric(svcType)
                .As(typeof(IService<>))
                .AsImplementedInterfaces();
            }

            _ioc = container.Build();
        }

        [Test]
        public void SingleOpenGenericResolveTest()
        {
            var reg = new Region { };

            var actual = _ioc.Resolve<IService<Region>>();
            Assert.That(actual != null);

            actual.DoSomething(reg);
        }

        [Test]
        public void MultiOpenGenericResolveTest()
        {
            //works
            var actual1 = _ioc.Resolve<IService<Region>>();
            Assert.That(actual1 != null);

            //works only with manual registration
            var actual2 = _ioc.Resolve<IService<City<Region>>>();
            Assert.That(actual2 != null);

            //works only with manual registration
            var actual3 = _ioc.Resolve<IService<Address<City<Region>,Region,SomethingElse>>>();
            Assert.That(actual3 != null);
        }
    }
}
4

1 回答 1

0

问题是,如果你解决IService<T>了但实现需要不止一个泛型,Service<T,U,V>那么 Autofac 就无法知道其他类型(U,V)的来源......所以你试图用程序集注册它们的方式集体扫描是行不通的。

于 2016-02-27T23:56:50.293 回答