我有一个通用接口IDataService<T>
及其默认实现DataService<T>
。然后,某些类型具有其特定的服务接口,这些接口也实现IDataService
,例如:
public interface IClientService : IDataService<Client>
{
void SomeProcess();
}
public class ClientService : DataService<Client>, IClientService
{
public override SomeDataServiceMethodOverride();
public void SomeProcess();
}
如您所见,ClientService
是一个专门的IDataService<Client>
,它扩展了DataService<Client>
的功能并实现了另一个接口。
我想要的是,当我要求 StructureMap 进行IDataService<Client>
时,它会给我一个ClientService
,但是当我要求IDataService<OtherEntity>
时,它只是回退到默认的实现DataService<OtherEntity>
。到目前为止,我在结构图配置中拥有的是:
Scan(
scan => {
scan.AssemblyContainingType<IClientService>();
scan.AssemblyContainingType<ClientService>();
scan.WithDefaultConventions();
});
For(typeof(IDataService<>)).Use(typeof(DataService<>));
但问题是它在请求IDataService<Client>
时没有实例化ClientService
,而是DataService<Client>
。现在我将最后一行更改为:
For(typeof(IDataService<OtherEntity>)).Use(typeof(DataService<OtherEntity>));
但是,对于任何没有具体服务实现的实体,我都必须这样做。如何自动执行此操作?
从您的描述来看,听起来您想注册具体服务类型上的所有接口。 StructureMap 通过提供定义应用于扫描操作的自定义约定的功能来实现这一点。定义实现StructureMap.Graph.IRegistrationConvention
的类型,然后定义ScanTypes
方法。 该方法提供扫描类型的集合和存储自定义配置的注册表。
以下代码片段在功能上等效于此处找到的 StructureMap 文档中的代码。
public class AllInterfacesConvention : StructureMap.Graph.IRegistrationConvention
{
public void ScanTypes(TypeSet types, Registry registry)
{
foreach(Type type in types.FindTypes(TypeClassification.Concretes | TypeClassification.Closed)
{
foreach(Type interfaceType in type.GetInterfaces())
{
registry.For(interfaceType).Use(type);
}
}
}
}
然后,您可以更新扫描操作以应用此约定。
var container = new Container(x => {
x.For(typeof(IDataService<>)).Use(typeof(DataService<>));
// Override custom implementations of DataService<>
x.Scan(scanner => {
scan.AssemblyContainingType<IClientService>();
scan.AssemblyContainingType<ClientService>();
scan.Convention<AllInterfacesConvention>();
});
});
// This should now be of type ClientService
var service = container.GetInstance<IDataService<Client>>();