在ASP.NET MVC 4中使用StructureMap自定义约定的单例

时间:2013-04-12 13:01:58

标签: asp.net-mvc-4 singleton structuremap

我在尝试让 singleton 生命周期与StructureMap中的自定义约定一起使用时遇到问题。

基本上我有一个自定义的注册表类型类,它包含一个我想成为单例的字典,以便在启动应用程序时创建一次。< / p>

我创建了一个自定义约定,它会查看某个类的属性,并确定该类是否应为 HttpContextScoped 辛格尔顿

问题是,当我使用Visual Studio调试器运行应用程序时,应该是一个单例的对象的构造函数每次都会被调用加载网页而不是像我预期的那样发生一次。看起来该对象表现为 HttpContextScoped 而不是 Singleton

以下是一些细节:

app_start 文件夹中

StructuremapMvc

public static class StructuremapMvc
    {
        public static void Start()
        {
            IContainer container = IoC.Initialize();
            DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
            GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(container);
        }
    }

Ioc

public static IContainer Initialize()

ObjectFactory.Initialize(x =>
{
    x.Scan(scan =>
            {
                scan.TheCallingAssembly();
                scan.AssemblyContainingType<IConfigManager>();
                scan.WithDefaultConventions();
                scan.Convention<CustomConvention>();
            });

CustomConvention : IRegistrationConvention  

public void Process(Type type, Registry registry) public void Process(Type type, Registry registry)
        {
            var attributes = type.GetCustomAttributes(false);
            if (attributes.Length > 0)
            {
                if (attributes[0] is SingletonAttribute)
                {
                    registry.For(type).Singleton();
                }
                else if (attributes[0] is HttpContextScopedAttribute)
                {
                    registry.For(type).HttpContextScoped();
                }
            }
        }


[Singleton]
public class MyRegistry : IMyRegistry

1 个答案:

答案 0 :(得分:1)

这个问题似乎已经很老了,但无论如何我都会回答它,因为可能还有其他人遇到了与Structure map相同的问题。在某些情况下,单个insance是“每个实例”创建的,指的是它们被注入的实例。这意味着当它们被注入其他地方时,你可以拥有不同的“singleton”实例。我个人在MVC应用程序中看到了WEBAPI的这种行为。

我能使其成为“真正的”全局单例的唯一方法是使用具有特定类型参数的通用接口来区分要使用的不同类型:

public interface ITest<T>
{
}

public class Test1 : ITest<int>
{
}

public class Test2 : ITest<string>
{
}

Scan(x =>
        {
            x.TheCallingAssembly();
            x.IncludeNamespace("MvcApplication1");
            x.ConnectImplementationsToTypesClosing(typeof(ITest<>))
                .OnAddedPluginTypes(a => a.LifecycleIs(InstanceScope.Singleton));
        });

我知道这不像上面描述的方法那样优雅也不实用,但至少它按预期工作。其他有效的方法是一对一地进行标准映射:

For<ISingleton>().Singleton().Use<Singleton>();