我有一个大型ASP.Net网络应用程序,它始终使用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的一个实例。)
任何人都可以放弃任何光明吗?
答案 0 :(得分:4)
您只需要将返回的类型约束为使用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