StructureMap 2.6.1 和 ASP.NET MVC 2 问题(来自 DI 的完全初学者)

发布于 2024-10-01 21:06:21 字数 1362 浏览 0 评论 0原文

根据在另一个线程上与 @Aaronaught 的对话,我已经开始将我的应用程序转换为使用依赖项注入和存储库模式,但我有点卡住了。我想我已经掌握了模式的大部分内容和流程,但我一直坚持将 StructureMap 实现到 ASP.NET MVC 2 中。我读过的示例似乎与我所使用的最新版本的 StructureMap 已经过时了。正在使用(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),所以我不确定如何编写它......

我将非常感谢任何帮助填补我的空白。

PS 我对依赖注入和存储库的体验总计大约 8 小时。

更新/结论

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

我不知道 Ninject 是否比 StructureMap 更好,但从我的角度来看,它绝对更容易开始使用。

Per a conversation with @Aaronaught on another thread, I've started converting my application to use Dependency Injection and the Repository patterns, but I'm a little stuck. I think I get most of the stuff and flow of the patterns, but I'm stuck on implementing StructureMap into ASP.NET MVC 2. The examples I've read seem to be out of date with the latest version of Structure Map which I'm using (2.6.1).

I'm hoping that someone can fill in the gaps based on the code I paste below:

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

With this I can get an instance of the DataContext from within my controller(s) with:

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

I know that's wrong to do, but I'm confused on how to avoid it. Moving on, here's the controller factory:

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

I don't understand exactly what this does, but it's in the examples, so I'm replicating it. Can someone explain it to me?

Now from what I understand, there's supposed to be registries which if I understand correctly, globalize object instances such as the DataContext. Is that correct? If so, how do I go about writing the registry for StructureMap 2.6.1? The example code I've seen seems obsolete because when I write it I don't have the same options available to me (via IntelliSense), so I'm not sure how to write it...

I will really appreciate any help in filling in the gaps that I have.

P.S. My experience with Dependency Injection and Repositories is about 8 hours total.

UPDATE/CONCLUSION

Having read through @Pure's excellent explanation below and watching the tekpub video he referenced in a sub-comment I've opted out for Ninject over StructureMap.

I don't know if Ninject is better than StructureMap, but from my stand point it's definitely much easier to start out with and get going.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

同尘 2024-10-08 21:06:21

好的,

我确信 Jeremy Miller 会更正我的帖子并为您提供事实如此,但是拥有使用 StructureMap 创建控制器的自定义 Controller 工厂 的想法是因为 Controller 类关键类,其中大部分逻辑开始并发生(是的,有动作过滤器和之前发生的东西,但让我们保持简单) - 这需要预先拥有所有依赖项在任何逻辑开始之前进行设置。

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

这是 DI/IoC 的核心。

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


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

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

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

所以当我们使用这种方法时,我们也不应该关心产品信息存在于哪里。我们只想用这个名为“产品”的东西做一些事情。

好吧..那么让我们用它做点什么...

public ActionMethod Index()
{
   var products = _myProductService.Find().ToList();

   // .. rest snipped.
}

好吧..到目前为止,我们现在要求一些服务来查找所有产品,然后列出它们。基尔。尽管如此,我们并不关心这些产品的来源。或者甚至,这个产品服务是什么。这就是关键-> 我们让 DI/IoC 来担心这个问题。我们所关心的是我们有一些ProductService,它可以对某些产品执行一些操作。在本例中,它将查找所有产品,然后我们要求它列出找到的所有产品。

那么 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 说:

我需要一个 IProductService 和一个 ILoggingService 实例。我将其传递给 HomeController 构造函数
...你能给我那些吗?”

然后 StructureMap 说:

好的..首先-> IProductService。让我们看看这里,您已将 IProductService 映射到
您创建的自定义类,名为 ReallyFastProductService。库尔,我会创造出那些坏男孩之一。
接下来,您将 ILoggingService 映射到 NLogLoggingService 类...很好!
NLog wroxs,伙计。所以我也会创造一个坏男孩。好的,我现在已经做了这两个实例。
最后!我现在可以创建您想要的 HomeController 的实例..
然后我将把我刚刚创建的两个对象传递到 HomeController 构造函数中......还有中提琴!这是控制器实例。

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

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

惊人的!因此,这意味着 Index() 方法永远不会紧密耦合到类的特定实现。

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

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

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

...,那么 HomeController 中的所有方法现在都会引用您刚刚构建的新类中的逻辑。无需更改控制器中的任何代码。

抓住掉落的一分钱:)

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

在此处输入图像描述

OK,

I'm sure Jeremy Miller will correct my post and give you the real truth, but the idea of having that custom Controller factory which uses StructureMap to create the controllers, is because the Controller class is the key class where the majority of the logic kicks off and takes place (Yes, there's action filters and stuff that happens before, but lets keep this simple) - and this needs to have all the dependencies pre-setup before any logic begins.

So the idea is this. If all the logic and magic-unicorn stuff happens in the Controllers methods, then when we first enter the method ... we need to have all our requirements already setup. More importantly, each method in any Controller shouldn't care about what requirement (ie. instances) it has .. just that someone, from somewhere. .. has already made this decision and given me all the important objects that we might require.

This is core of what DI/IoC is all about.

So lets use some really simple code to explain this, cause I'm not good at explaining things.


Lets assume we have the following method in the Controller :-

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

Pretty simple. Just lists some products to the browser. So the first thing you need to ask is this -> what are Products? where do they come from? Well, the controller method doesn't ask this question at all. In fact, it DOESN'T CARE where they came from. It only cares that it has something that is a Product.

So when we are in this method, we also shouldn't care about where the product information exists at. We just want to do something with this things called Products'.

Ok .. so lets do something with it ...

public ActionMethod Index()
{
   var products = _myProductService.Find().ToList();

   // .. rest snipped.
}

Ok .. so far we now are asking some Service to find all the products and then list them. Kewl. Still, we don't care where these products originate from. Or even, what is this Product Service. That's the key -> We leave the DI/IoC to worry about that. All we care about is the fact that we have some ProductService which does some stuff with some products. In this case, it's going to Find all the products and then we ask it to List all the products, found.

So where does DI/IoC come into play?

This is the unicorn-magic part :)

When this controller was instanciated, it asked StructureMap :

"Oi! StructureMap! I need to create a
HomeController. But The HomeController
has at least one constructor.. and the
most complex constructor it has (note:
DI/IoC call this the most greedy
constructor
) lists a number of
objects which it requires. So ... I
need to create those objects first,
then create my HomeController .. and
pass those objects in.pass those objects in.

Lets look at the code...

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.
    }
}

whoa -- there's a few things going on here.
Lets recap -> So StructureMap says:

I need an instance of a IProductService and an ILoggingService .. which I pass to the HomeController constructor
... can u give me those please?"

And StructureMap then says:

Ok .. first up -> an IProductService. Lets see here, U've mapped an IProductService to a
custom class you made, called ReallyFastProductService. Kewl, i'll create one of those bad boys.
Next, u've mapped an ILoggingService to an NLogLoggingService class ... nice!
NLog wroxs, dude. So i'll also create one of those bad boys. Ok, i've now made those two instances.
Finally! I can now make an instance of the HomeController you're after ..
and then i'll pass those two objects i just made, into the HomeController constructor... and viola! here's the Controller instance.

... so now, u have the Controller instance.

.... and when u step into the Index() method, if u use the mouse and hover over the instances, they will be a ReallyFastProductService and an NLogLoggingService.

Awesome! So this means that the Index() method is never tightly coupled to a particular implementation of a class.

Now, u decided that u didn't like all the code you did in the ReallyFastProductService and decided to code up another one, that takes use of some new tricks and skills you just picked up. So now you make a 2nd class called, PewPewProductService, because it pwns. Now, if u change your StructureMap mapping from...

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

to

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

... suddenly, all the methods in that HomeController now refer to the logic in the new class you just built. No need to change any code in the Controller.

Catch the penny as it drops :)

Welcome to DI/IoC and why it kicks serious butt.

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文