Unity IOC - 如何注册基于自定义属性的类型
本文关键字:自定义属性 类型 注册 IOC 何注册 Unity | 更新日期: 2023-09-27 18:37:22
我有一个大型 ASP.Net Web应用程序,它始终使用Unity IOC。 有许多类需要创建为单例。
这是我的 UnityConfig 中代码的第一部分.cs在我的启动项目中:
// Create new Unity Container
var container = new UnityContainer();
// Register All Types by Convention by default
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.Transient);
到目前为止,我已经专门在 Unity IOC 容器中使用生存期管理器注册了每个单一实例类型,如下所示:
container.RegisterType<IMySingleton1, MySingleton1>(new ContainerControlledLifetimeManager());
container.RegisterType<IMySingleton2, MySingleton2>(new ContainerControlledLifetimeManager());
但是,我想避免以这种方式将每个类型专门注册为单一实例,而是通过使用自定义 SingletonAttribute 标记它们来确定加载程序集中的哪些类型需要是单一实例,然后,如果可能,将它们集体注册。
我为此创建了一个自定义属性:
[AttributeUsage(AttributeTargets.Class)]
public class SingletonAttribute : Attribute {}
并相应地标记了类定义:
[Singleton]
public class MySingleton : IMySingleton
{
...
}
我已经设法选择了具有此自定义属性的所有类型:
static IEnumerable<Type> GetTypesWithSingletonAttribute(Assembly assembly)
{
foreach (Type type in assembly.GetTypes())
{
if (type.GetCustomAttributes(typeof(SingletonAttribute), true).Length > 0)
{
yield return type;
}
}
}
我在 UnityConfig 中有以下代码.cs:
// Identify Singleton Types
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
List<Type> singletonTypes = new List<Type>();
foreach (var assembly in assemblies)
{
singletonTypes.AddRange(GetTypesWithSingletonAttribute(assembly));
}
所以,我现在有一个包含所有必需类型的枚举,但我看不出如何按类型将它们注册为单例,同时仍然允许它们按约定解析(即,Unity 知道 IMySingleton 应该解析为 MySingleton 的实例)。
谁能透露任何光芒?
你只需要将返回的类型约束为使用 Singleton
属性批注的类型:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies()
.Where(t => t.GetCustomAttributes<SingletonAttribute>(true).Any()),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
您可以注册所有内容,然后用ContainerControlledLifetimeManager
覆盖任何单例的注册:
// Register All Types by Convention by default
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.Transient);
// Overwrite All Types marked as Singleton
container.RegisterTypes(
AllClasses.FromLoadedAssemblies()
.Where(t => t.GetCustomAttributes<SingletonAttribute>(true).Any()),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled,
null,
true); // Overwrite existing mappings without throwing