结构图加载默认的通用实现(如果不存在专用)

本文关键字:如果不 如果 不存在 专用 实现 默认 加载 结构图 | 更新日期: 2023-09-27 18:31:29

我有一个通用接口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>>();