【问题标题】:StructureMap 2.6.1 and ASP.NET MVC 2 Questions (from a complete beginner in DI)StructureMap 2.6.1 和 ASP.NET MVC 2 问题(来自 DI 的完整初学者)
【发布时间】:2010-11-11 02:07:04
【问题描述】:

根据在另一个线程上与@Aaronaught 的对话,我已经开始将我的应用程序转换为使用依赖注入和存储库模式,但我有点卡住了。我想我得到了模式的大部分内容和流程,但我坚持将 StructureMap 实现到 ASP.NET MVC 2 中。我读过的示例似乎与我最新版本的结构图已经过时了正在使用 (2.6.1)。

我希望有人可以根据我在下面粘贴的代码来填补空白:

public static class Bootstrapper {
    public static void Configure() {
        ObjectFactory.Configure(x => {
            x.For<DataContext>().Add(new DataContext());
        });
    }
}

有了这个,我可以从我的控制器中获取一个 DataContext 的实例:

protected DataContext dc = ObjectFactory.GetInstance<DataContext>();

我知道这样做是错误的,但我对如何避免它感到困惑。继续,这里是控制器工厂:

public class StructureMapControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(
        RequestContext rc,
        Type ct) {
        return (ObjectFactory.GetInstance(ct) as Controller);
    }
}

我不明白这是做什么的,但它在示例中,所以我正在复制它。谁能给我解释一下?

现在据我了解,应该有注册表,如果我理解正确的话,可以将对象实例全球化,例如 DataContext。那是对的吗?如果是这样,我该如何为 StructureMap 2.6.1 编写注册表?我看到的示例代码似乎已经过时了,因为当我编写它时,我没有可用的相同选项(通过 IntelliSense),所以我不知道如何编写它......

如果能帮助我填补我的空白,我将不胜感激。

附:我在依赖注入和存储库方面的经验总共大约 8 小时。

更新/结论

在阅读了下面@Pure 的出色解释并观看了他在子评论中引用的 tekpub 视频后,我选择了 Ninject 而不是 StructureMap。

我不知道 Ninject 是否比 StructureMap 更好,但从我的角度来看,它肯定更容易开始和开始。

【问题讨论】:

    标签: asp.net-mvc dependency-injection structuremap repository-pattern


    【解决方案1】:

    好的,

    我确信Jeremy Miller 会更正我的帖子并告诉你真实情况,但是使用StructureMap 创建控制器的自定义Controller factory 的想法是因为Controller class 是key class 大部分逻辑开始并发生的地方(是的,之前发生过动作过滤器和其他东西,但让我们保持简单) - 这需要预先拥有所有依赖项-在任何逻辑开始之前设置。

    所以想法是这样的。如果所有的逻辑和魔法独角兽的东西都发生在Controllers 方法中,那么当我们第一次进入该方法时......我们需要已经设置了所有需求。更重要的是,任何控制器中的每个方法都不应该关心它有什么要求(即实例) .. 只是某个人,来自某个地方。 .. 已经做出了这个决定,并给了我我们可能需要的所有重要物品。

    这是 DI/IoC 的核心。

    所以让我们用一些非常简单的代码来解释这一点,因为我不擅长解释。


    假设我们在控制器中有以下方法:-

    public ActionMethod Index()
    {
       // List all Products.
    }
    

    很简单。只是向浏览器列出一些产品。所以你需要问的第一件事是 -> Products 是什么?他们来自哪里?好吧,控制器方法根本不问这个问题。事实上,它并不关心他们来自哪里。它只关心它有 somethingProduct

    所以当我们采用这种方法时,我们也不应该关心产品信息存在于何处。我们只是想用这个叫做Products'的东西做点什么。

    好的..让我们用它做点什么...

    public ActionMethod Index()
    {
       var products = _myProductService.Find().ToList();
    
       // .. rest snipped.
    }
    

    好的 .. 到目前为止,我们现在要求一些服务来查找所有产品,然后列出它们。科尔。尽管如此,我们并不关心这些产品的来源。甚至,这是什么Product Service。这是关键 -> 我们让 DI/IoC 来担心这个。我们所关心的是我们有一些ProductService 对一些产品做一些事情。在这种情况下,它会去Find所有产品,然后我们要求它列出所有找到的产品。

    那么 DI/IoC 在哪里发挥作用?

    这是独角兽魔法部分:)

    当这个控制器被实例化时,它询问了 StructureMap:

    “Oi!StructureMap!我需要创建一个 家庭控制器。但是 HomeController 至少有一个构造函数..和 它拥有的最复杂的构造函数(注意: DI/IoC 称之为最贪婪 构造函数) 列出了一些 它需要的对象。所以我 需要先创建这些对象, 然后创建我的 HomeController .. 和 把那些对象传进去。把那些对象传进去。

    让我们看看代码...

    public class HomeController : Controller
    {
        private IProductService _productService;
        private ILoggingService _loggingService;
    
        public HomeController(IProductService productService, ILoggingService loggingService)
        {
           _productService = productService;
           _loggingService = loggingService;
        }
    
        public ActionMethod Index()
        {
            var products = _productService.Find().ToList();
    
            // rest snipped.
        }
    }
    

    哇——这里发生了一些事情。 让我们回顾一下 -> 所以 StructureMap 说:

    我需要一个 IProductServiceILoggingService 的实例,我将它们传递给 HomeController 构造函数 ……你能给我那些吗?”

    然后 StructureMap 说:

    好的 .. 首先 -> 一个 IProductService。让我们在这里看看,你已经将一个 IProductService 映射到一个 您制作的自定义类,称为ReallyFastProductService。 Kewl,我会创造一个坏男孩。 接下来,您已将 ILoggingService 映射到 NLogLoggingService 类...很好! NLog wroxs,伙计。所以我也会创造一个坏男孩。好的,我现在已经制作了这两个实例。 最后!我现在可以创建您所追求的 HomeController 的实例.. 然后我将把我刚刚制作的这两个对象传递给 HomeController 构造函数......和中提琴!这是控制器实例。

    ...所以现在,你有了控制器实例。

    ....当您进入 Index() 方法时,如果您使用鼠标并将鼠标悬停在实例上,它们将是 ReallyFastProductServiceNLogLoggingService

    太棒了!所以这意味着Index() 方法永远不会紧密耦合到类的特定实现。

    现在,你决定你不喜欢你在ReallyFastProductService 中所做的所有代码,并决定编写另一个代码,它利用了你刚刚学到的一些新技巧和技能。所以现在你创建了一个名为 PewPewProductService 的第二类,因为它是 pwns。现在,如果你改变你的 StructureMap 映射...

    ObjectFactory.Configure(x => 
        { x.For<IProductService>().Add(new ReallyFastProductService());});
    

    ObjectFactory.Configure(x => 
        { x.For<IProductService>().Add(new PewPewProductService());});
    

    ...突然间,HomeController 中的所有方法现在都引用了您刚刚构建的新类中的逻辑。无需更改Controller中的任何代码。

    抓住落下的一分钱 :)

    欢迎来到 DI/IoC 以及它为何如此重要。

    【讨论】:

    • 哇..那太好了。我看到我还有很多东西要学。请问我在哪里可以了解有关此主题的更多信息?
    • 感谢@Pure 的解释,你的措辞让我哈哈大笑。 :) 不管怎样,我看了 tekpub 视频,我喜欢在 StructureMap 上设置 Ninject 是多么简单,所以我最终切换到它,它更容易。现在我得去学习存储库模式,这很神奇。再次感谢您的帮助!
    • @Alex - 快乐 :) DI/IoC 和存储库模式现在 (IMO) 是一些最初的模式/魔法/技巧,我确保所有新程序员在了解基础知识后都会学习。就个人而言,我更喜欢 SM 而不是 Ninject,但这是一场宗教战争,每个人都是对的 :) 很高兴我的帖子有帮助 :) 现在,去拿他们!
    • 即使是作为一名长期 Java 程序员和 C# 的我,也让我发笑,玩得开心,实际上“哇”的解释,简直震撼了 Pure!很好
    猜你喜欢
    • 1970-01-01
    • 2010-10-30
    • 2019-04-11
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    相关资源
    最近更新 更多