[英]Register and resolve open generic types with many generic parameters with Autofac
I would like to resolve an open generic service due to a generic interface. 由于通用接口,我想解决一个开放的通用服务。 I use autofac.
我使用autofac。
Each concrete service works only with concrete classes. 每个具体服务仅适用于具体类。
I can resolve only one service with single generic param
[see SingleOpenGenericResolveTest
]. 我只能使用单个
generic param
来解析一项服务[请参见SingleOpenGenericResolveTest
]。 Is it possible to register & resolve many services with many T-params
[see MultiOpenGenericResolveTest
]? 是否可以使用许多
T-params
注册和解析许多服务[请参见MultiOpenGenericResolveTest
]?
I added only one of concrete classes for IService
but it possible to be many classes of T
. 我仅为
IService
添加了一个具体的类,但可能有T
许多类。 ( TRegion : Region, TRegion : BigRegion
, etc...) (
TRegion : Region, TRegion : BigRegion
等)
Here is NUnit 3 tests or you can download my solution here : https://www.dropbox.com/s/vqmdwb6hwmzgjrb/AutofacResolveTests.zip?dl=0 这是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);
}
}
}
问题是,如果您解析IService<T>
但是实现需要多个像Service<T,U,V>
这样的泛型,则Autofac无法知道其他类型(U,V)的来源...因此,您尝试向程序集扫描进行整体注册的方法将行不通。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.