Register Interface in Unity Container 基于Marker 接口进入不同的Lifetime

Register Interface in Unity Container based on Marker interface into different Lifetime

我的解决方案中有多个项目:

Core
Repository
Service
WebAPi

我的 Unity 注册是在 WebAPI 项目上。

我想要实现的是我过去在温莎城堡所做的事情,现在我想通过 Unity 来实现:使用约定注册接口 https://github.com/castleproject/Windsor/blob/master/docs/registering-components-by-conventions.md

我有两个标记界面。

public interface ISingletonDependency{}
public interface ITransientDependency{}

对于我的存储库或服务中的 classes,我这样做:

public interface IPersonRepository:ISingletonDependency{
...
...

}

public class PersonRepository: IPersonRepository{
...
...
...
}

为我服务class:

public interface IPersonService:ISingletonDependency{
...
...    
}

public class PersonService: IPersonService{
...
...
...
}

我对我的所有 classes 都以类似的方式对 DI 执行此操作,并且在注册期间我曾经这样做过:

container.Register(
    Classes.NamedAssembly("SolutionName.Repository")
        .BasedOn<ISingletonDependency>()
        .WithService.FromInterface().LifestyleSingleton()
);


container.Register(
    Classes.NamedAssembly("SolutionName.Service")
        .BasedOn<ISingletonDependency>()
        .WithService.FromInterface().LifestyleSingleton()
);


container.Register(
    Classes.NamedAssembly("SolutionName.Repository")
        .BasedOn<ITransientDependency>()
        .WithService.FromInterface().LifestyleTansient()
);


container.Register(
    Classes.NamedAssembly("SolutionName.Service")
        .BasedOn<ITransientDependency>()
        .WithService.FromInterface().LifestyleTansient()
);

这样我就不需要为每个人都这样做,我在 Unity 中看到了方法,但它是基于命名约定的 并且您不能单独指定单身或短暂的生活方式。

https://blogs.msdn.microsoft.com/agile/2013/03/12/unity-configuration-registration-by-convention/

有没有一种方法可以像我上面给出的例子那样,基于标记界面,在温莎城堡中做你能做的事情?

鉴于:

public interface ISingletonDependency { }
public interface ITransientDependency { }

public interface IPersonRepository : ISingletonDependency { }
public class PersonRepository : IPersonRepository { }

public interface IPersonService : ITransientDependency { }
public class PersonService : IPersonService { }

然后您可以使用以下方式注册类型:

var container = new UnityContainer();

container.RegisterTypes(
    AllClasses.FromAssembliesInBasePath().Where(
        // Could also match on namespace etc. here
        t => t.Assembly.GetName().Name.StartsWith("SolutionName")),
    WithMappings.FromMatchingInterface,
    WithName.Default,
    WithLifetime.FromMarkerInterface);

// Singleton
Debug.Assert(ReferenceEquals(container.Resolve<IPersonRepository>(), container.Resolve<IPersonRepository>()));

// Transient
Debug.Assert(!ReferenceEquals(container.Resolve<IPersonService>(), container.Resolve<IPersonService>()));

WithLifetime.FromMarkerInterface 是一个自定义约定,它使用标记界面 select 正确的 LifetimeManager:

public static class WithLifetime
{
    public static LifetimeManager FromMarkerInterface(Type type)
    {
        if (typeof(ISingletonDependency).IsAssignableFrom(type))
        {
            return new ContainerControlledLifetimeManager();
        }

        return new TransientLifetimeManager();
    }
}

在这种情况下,一切都是瞬态的,除非它是 ISingletonDependency,但您可以使规则更明确(例如,如果未找到有效的标记接口,则抛出)。

如果您可以在 AllClasses.FromAssembliesInBasePath().Where 中缩小 where 子句的范围,那么您可能只需要一行即可:

container.RegisterTypes(
AllClasses.FromAssembliesInBasePath().Where(
    t => t.Namespace.StartsWith("SolutionName.Repository") || 
         t.Namespace.StartsWith("SolutionName.Service")),
    WithMappings.FromMatchingInterface,
    WithName.Default,
    WithLifetime.FromMarkerInterface);