通过 Scan 方法向 StructureMap 注册类型

Registering types with StructureMap via Scan method

我在其他程序集中有 IService 接口和许多 IService 实现。我需要将所有实现注册为 IService 和具体 IService 实现之间的继承链中类型的服务。 例如:

public interface IService{}
public abstract class BaseService<T>: IService{}

并且在另一个程序集中:

public class SomeSpecialService: BaseService<SomeType>{}
public class AnotherSpecialService: BaseService<AnotherType>{}

因此,我需要将 SomeSpecialService 注册为 BaseService<SomeType> 的服务,并将 AnotherSpecialService 注册为 BaseService<AnotherType> 的服务。

目前,我通过反射逐一注册每个实现来做到这一点。

1) 是否可以使用 Scan() 表达式?

2) 如果 SomeSpecialService 是内部的(非 public)class,是否可以在另一个程序集中使用 Scan() 表达式?

您可以使用:

        var container = new Container(
            c => c.Scan(
                s =>
                    {
                        s.TheCallingAssembly();
                        s.AddAllTypesOf(typeof(BaseService<>));
                    }));

如果您有多个 BaseService<> 的具体通用参数实现(例如 BaseService<SomeType>),您需要命名注册并按名称解析它们。

        var container = new Container(
            c => c.Scan(
                s =>
                    {
                        s.TheCallingAssembly();
                        s.AddAllTypesOf(typeof(BaseService<>)).NameBy(t => t.Name);
                    }));

        var service = container.GetInstance<BaseService<SomeType>>("BaseServiceForSomeType");

当每个泛型参数只有一个实现并且需要默认生命周期(瞬态)以外的实现时,您可以使用 s.ConnectImplementationsToTypesClosing(typeof(BaseService<>)).OnAddedPluginTypes(c => c.Singleton());

当您在注册类型时需要更多自定义时,您可以定义注册约定。

        public class BaseServiceConvention : IRegistrationConvention
        {
            public void Process(Type type, Registry registry)
            {
                if (!type.IsConcrete())
                {
                    return;
                }

                var interfaceTypes = type.FindInterfacesThatClose(typeof(BaseService<>));

                foreach (var closedGenericType in interfaceTypes)
                {
                    if (GenericsPluginGraph.CanBeCast(closedGenericType, type))
                    {
                        registry.For(closedGenericType).Singleton().Use(type).Named(type.Name);
                    }
                }
            }
        }

然后你像这样应用这个约定:

        var container = new Container(
                c => c.Scan(
                    s =>
                        {
                            s.TheCallingAssembly();
                            s.Convention<BaseServiceConvention>();
                        }));

希望对您有所帮助!