Unity IOC - 如何根据自定义属性注册类型?

时间:2016-03-04 19:39:12

标签: c# asp.net inversion-of-control unity-container ioc-container

我有一个大型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的一个实例。)

任何人都可以放弃任何光明吗?

1 个答案:

答案 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