使用具有结构映射的命名会话实例策略的Setter insection

时间:2009-07-15 07:56:14

标签: c# .net asp.net dependency-injection inversion-of-control

我正在使用Structure map并希望将实例(由容器构造)注入到控制器的属性中。应该将实例命名并存储在http会话上下文容器中。 在我的应用程序的先前版本中,我使用了自定义DI框架,并且很容易做出这样的事情:

public class MyController : Controller
{
    [InjectSession("MySessionInstanceKey")]
    public MyManager Manager {get; set;}
}

有没有简单的方法来使用structuremap?
或者我可以将自定义属性和注入逻辑引入SM框架(以某种方式扩展框架)?
请帮我找到解决这个问题的方法,非常感谢!

P.S。我找到了临时解决方案,但它增加了控制器与IoC框架的凝聚力,并包含大量代码:

private const string ordersBulkManagerKey = "_OrdersBulkManager";
public BulkManager OrdersBulkManager
{
    get
    {
        var manager = Session[ordersBulkManagerKey] as BulkManager;
        if(manager == null)
        Session[ordersBulkManagerKey] = manager
            = ObjectFactory.GetInstance<BulkManager>();
        return manager;
    }
}

所以,我不想在那里使用ObjectFactory.GetInstance ......

2 个答案:

答案 0 :(得分:2)

有一些关于如何将ASP.NET MVC和StructureMap连接在一起的博客文章。 (因此以下大部分代码都是各种帖子的摘要。)

实现这一目标的常用方法是声明我们自己的控制器工厂类,这将允许我们通过构造函数注入依赖项。 (ASP.NET MVC使用的默认控制器工厂需要存在默认构造函数)

因此,在MyController类中,您将拥有一个接受MyManager参数的构造函数(将由我们自己的控制器工厂类为您注入)

public class MyController : Controller
{
   private readonly ISomeService _someService;
   //Constructor Injection. 
   public MyController(ISomeService someService){
       _someService = someService;
    }
}

接下来,您将配置ASP.NET MVC使用这个新的控制器工厂类(我们将调用StructureMapControllerFactory)。

protected void Application_Start()
{

   //This is where you register your concrete types with StructureMap
    Bootstrapper.ConfigureStructureMap();

    //Our very own Controller Factory
    ControllerBuilder.Current.SetControllerFactory
    (new StructureMapControllerFactory());

    RegisterRoutes(RouteTable.Routes);
}

在StructureMapControllerFactory中,我们调用ObjectFactory.GetInstance给你返回控制器(前提是我们连接了所有依赖项)

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        if (controllerType == null) return null;
        try
        {
            return ObjectFactory.GetInstance(controllerType) as Controller;
        }
        catch (StructureMapException)
        {
            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
            throw;
        }
    }
}

希望我的解释清楚,但如果不是,请告诉我,我可以扩展它。

顺便说一下,下面的代码片段是一个关于你的引导程序代码的示例。

public static class Bootstrapper 
{
    public static void ConfigureStructureMap()
    {
        ObjectFactory.Initialize(
         x => x.AddRegistry(new MyApplicationRegistry()));            
    }
}

public class MyApplicationRegistry : Registry
{
    public MyApplicationRegistry()
    {
         ForRequestedType<ISomeService>()
         .CacheBy(InstanceScope.Your_Choice_Here)
         .TheDefault.Is.OfConcreteType<SomeService>();
    }
}

注意:有关各种InstanceScope选项,请参阅StructureMap文档。

答案 1 :(得分:2)

StructureMap可以控制你的对象生命周期,所以你不必自己实现它

For<IBulkManager>()
    .LifecycleIs(Lifecycles.GetLifecycle(InstanceScope.HttpSession))
    .Use<BulkManager>();

所以你的代码会变成

public IBulkManager OrdersBulkManager
{
    get { return ObjectFactory.GetInstance<IBulkManager>(); }
}