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);
我的解决方案中有多个项目:
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);