结构图IContainer实现

时间:2014-12-20 00:00:52

标签: c# .net structuremap

我现在正试图弄清楚结构图,因为ObjectFactory静态函数已被标记为过时。

从长远来看,我必须在MVC和WebApi应用程序中使用它。以前使用时,在global.asax中放置一个静态方法的行,以使用ObjectFactory初始化所有内容。

 ObjectFactory.Initialize{
                container.For .....
 }

尝试将此转换为新的IContainer方法我已经提出以下内容但是我想知道我是否实际上无意中在我的方法中实现了这个经常提到的反模式。

返回容器的静态方法:

public class StructureMapConfig
 {
    public static IContainer GetContainer()
    {            
        return new Container(container =>
        {
            container.For<IUserService>().Use<UserService>();
            container.For<IStringService>().Use<StringService>();
            container.For<IUserRepository>().Use<UserRepository>();                
        });
    }
 }

Userservice的contstructor看起来像这样:

 public class UserService : IUserService
{
    private readonly IUserRepository _userRepository;
    private readonly IStringService _stringService;

     public UserService(IUserRepository userRepository, IStringService stringService)
      {
         _userRepository = userRepository;
         _stringService = stringService;
      }

最后,初始化(控制台应用中的此实例)看起来像这样:

    private static IUserService _userService;
    private static IContainer _container;

     static void Main(string[] args)
      {
         _container = StructureMapConfig.GetContainer();
         _userService = _container.GetInstance<IUserService>();
      }

所以我的问题。

  1. 我在这里做了什么严重的错误
  2. 在UserService中,我是否应该通过IContainer并使用对象工厂来获取实例,或者我应该保持原样。
  3. 从静态方法返回IContainer是最好的方法
  4. 如果这是一个MVC应用程序,最好在Global.asax中构建一次,或者控制器构造函数每次都应该调用静态方法。
  5. 感谢您的任何建议。

1 个答案:

答案 0 :(得分:5)

按顺序完成您的问题:

  
      
  1. 我在这里做了什么严重的错误
  2.   

不,我在这里看不到任何严重错误。我可以做一些改进,我很快就会谈到。

  
      
  1. 在UserService中,我是否应该将IContainer传入并使用   获取实例的对象工厂,或者我应该保持原样。
  2.   

在IContainer实例上注入UserService是正确的。如果您的控制器只需要UserService,那么为什么要注入整个容器。实际上,您只想注入减少不必要的耦合和依赖性所需的最低限度。

  
      
  1. 从静态方法返回IContainer是最好的方法
  2.   

在删除ObjectFactory然后是,通过静态方法返回容器的实例是那些不通过MVC的依赖性解析来管理其创建的类的常用方法。

  
      
  1. 如果这是一个MVC应用程序,最好的做法是在中创建一次   Global.asax或控制器构造函数应该调用静态   方法每次。
  2.   

Global.asax.cs中创建容器是最好的方法,因为它在Application_Start上完成了一次,但请参阅下面的建议,即每个http请求使用嵌套容器。

<强>改进: -

利用StructureMap的注册表:

而不是像这样直接引用依赖项:

public static IContainer GetContainer()
{            
    return new Container(container =>
    {
        container.For<IUserService>().Use<UserService>();
        container.For<IStringService>().Use<StringService>();
        container.For<IUserRepository>().Use<UserRepository>();                
    });
}

选择使用StructureMap的注册表。这样您就可以对依赖项进行分组(例如MVC特定的依赖项或特定于WebAPI的依赖项,如下所示:

public class WebsiteRegistry : Registry
{
    public WebsiteRegistry()
    {
        this.For<IUserService>().Use<UserService>();
        this.For<IStringService>().Use<StringService>();
        this.For<IUserRepository>().Use<UserRepository>();         
    }
}

然后加载您的注册表:

container.Configure(c => {
    c.IncludeRegistry<WebsiteRegistry>();
    c.IncludeRegistry<TaskRegistry>();
});

HTTP上下文绑定容器:

将StructMap与ASP.NET MVC或WebApi(或任何基于HTTP的应用程序)一起使用时的另一个推荐模式是使用绑定到每个HTTP请求的嵌套容器。这主要涉及在每个HTTP请求上创建一个新的嵌套容器,然后在请求结束时将其处理掉。这可确保在HTTP请求结束后立即处理会话对象,数据库连接或UoW上下文等依赖项。

我建议您查看this article,了解有关此问题的详细信息,并讨论如何设置此问题。

这与在StructureMap的创建者Jeremy Miller经常推荐的StructureMap.MVC5包中使用的技术完全相同。

自动注册依赖关系

不是手动注册StructureMap的每个依赖项,而是可以利用StructureMap's auto-registration。您还可以指定自己的扫描约定。