Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Pro ASP.NET MVC Framework phần 3 ppt
PREMIUM
Số trang
47
Kích thước
16.2 MB
Định dạng
PDF
Lượt xem
1823

Pro ASP.NET MVC Framework phần 3 ppt

Nội dung xem thử

Mô tả chi tiết

<configSections>

<section name="castle"

type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,

Castle.Windsor" />

<!-- ... leave all the other section nodes as before ... -->

</configSections>

Then, directly inside the <configuration> node, add a <castle> node:

<configuration>

<!-- etc -->

<castle>

<components>

</components>

</castle>

<system.web>

<!-- etc -->

You can put the <castle> node immediately before <system.web>. Finally, instruct

ASP.NET MVC to use your new controller factory by calling SetControllerFactory() inside

the Application_Start handler in Global.asax.cs:

protected void Application_Start()

{

RegisterRoutes(RouteTable.Routes);

ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());

}

At this point, it’s a good idea to check that everything still works as before when you run

your application. Your new IoC container should be able to resolve ProductsController when

ASP.NET MVC requests it, so the application should behave as if nothing’s different.

Using Your IoC Container

The whole point of bringing in an IoC container is that you can use it to eliminate hard-coded

dependencies between components. Right now, you’re going to eliminate

ProductsController’s current hard-coded dependency on SqlProductsRepository (which, in

turn, means you’ll eliminate the hard-coded connection string, soon to be configured else￾where). The advantages will soon become clear.

When an IoC container instantiates an object (e.g., a controller class), it inspects that type’s

list of constructor parameters (a.k.a. dependencies) and tries to supply a suitable object for

each one. So, if you edit ProductsController, adding a new constructor parameter as follows:

public class ProductsController : Controller

{

private IProductsRepository productsRepository;

public ProductsController(IProductsRepository productsRepository)

{

this.productsRepository = productsRepository;

}

CHAPTER 4 ■ SPORTSSTORE: A REAL APPLICATION 99

10078ch04.qxd 3/26/09 12:52 PM Page 99

public ViewResult List()

{

return View(productsRepository.Products.ToList());

}

}

then the IoC container will see that ProductsController depends on an IProductsRepository.

When instantiating a ProductsController,Windsor will supply some IProductsRepository

instance. (Exactly which implementation of IProductsRepository will depend on your

web.config file.)

This is a great step forward: ProductsController no longer has any fixed coupling to any

particular concrete repository. Why is that so advantageous?

• It’s the starting point for unit testing (here, that means automated tests that have their

own simulated database, not a real one, which is faster and more flexible).

• It’s the moment at which you can approach separation of concerns with real mental

clarity. The interface between the two application pieces (ProductsController and the

repository) is now an explicit fact, no longer just your imagination.

• You protect your code base against the possible future confusion or laziness of yourself

or other developers. It’s now much less likely that anyone will misunderstand how the

controller is supposed to be distinct from the repository and then mangle the two into a

single intractable beast.

• You can trivially hook it up to any other IProductsController (e.g., for a different data￾base or ORM technology) without even having to change the compiled assembly. This is

most useful if you’re sharing application components across different software projects

in your company.

OK, that’s enough cheerleading. But does it actually work? Try running it, and you’ll get an

error message like that shown in Figure 4-11.

Figure 4-11.Windsor’s error message when you haven’t registered a component

Whoops, you haven’t yet registered any IProductsRepository with the IoC container. Go

back to your web.config file and update the <castle> section:

100 CHAPTER 4 ■ SPORTSSTORE: A REAL APPLICATION

10078ch04.qxd 3/26/09 12:52 PM Page 100

<castle>

<components>

<component id="ProdsRepository"

service="DomainModel.Abstract.IProductsRepository, DomainModel"

type="DomainModel.Concrete.SqlProductsRepository, DomainModel">

<parameters>

<connectionString>your connection string goes here</connectionString>

</parameters>

</component>

</components>

</castle>

Try running it now, and you’ll find that things are working again. You’ve nominated

SqlProductsRepository as the active implementation of IProductsRepository. Of course, you

could change that to FakeProductsRepository if you wanted. Note that the connection string is

now in your web.config file instead of being compiled into the binary DLL.10

■Tip If you have several repositories in your application, don’t copy and paste the same connection string

value into each <component> node. Instead, you can use Windsor’s properties feature to make them all

share the same value. Inside the <castle> node, add <properties><myConnStr>XXX</myConnStr>

</properties> (where XXX is your connection string), and then for each component, replace the connec￾tion string value with the reference tag #{myConnStr}.

Choosing a Component Lifestyle

Castle Windsor lets you select a lifestyle for each IoC component—lifestyle options include

Transient, Singleton, PerWebRequest, Pooled, and Custom. These determine exactly when the

container should create a new instance of each IoC component object, and which threads

share those instances. The default lifestyle is Singleton, which means that only a single

instance of the component object exists, and it’s shared globally.

Your SqlProductsRepository currently has this Singleton lifestyle, so you’re keeping a sin￾gle LINQ to SQL DataContext alive as long as your application runs, sharing it across all

requests. That might seem fine at the moment, because so far all data access is read-only, but

it would lead to problems when you start editing data. Uncommitted changes would start

leaking across requests.

Avoid this problem by changing SqlProductsRepository’s lifestyle to PerWebRequest, by

updating its registration in web.config:

<component id="ProdsRepository"

service="DomainModel.Abstract.IProductsRepository, DomainModel"

type="DomainModel.Concrete.SqlProductsRepository, DomainModel"

lifestyle="PerWebRequest">

CHAPTER 4 ■ SPORTSSTORE: A REAL APPLICATION 101

10. That’s not a record-breaking feat—ASP.NET has native support for configuring connection strings in the

<connectionStrings> node of your web.config file anyway. What’s advantageous about IoC is that you

can use it to configure any set of component constructor parameters without writing any extra code.

10078ch04.qxd 3/26/09 12:52 PM Page 101

Then register Windsor’s PerRequestLifestyle module in your <httpModules> node:11

<httpModules>

<add name="PerRequestLifestyle"

type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule,

Castle.MicroKernel" />

<!-- Leave the other modules in place -->

</httpModules>

If you’re later going to deploy to an IIS 7 web server, then be sure to add the following

equivalent configuration to your web.config file’s <system.webServer>/<modules> node, too

(you’ll learn more about configuring IIS 7 in Chapter 14):

<remove name="PerRequestLifestyle"/>

<add name="PerRequestLifestyle" preCondition="managedHandler"

type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule,

Castle.MicroKernel" />

This is the great thing about IoC containers: the amount of work you can avoid doing.

You’ve just accomplished the DataContext-per-HTTP-request pattern purely by tweaking your

web.config file.

So that’s it—you’ve set up a working IoC system. No matter how many IoC components

and dependencies you need to add, the plumbing is already done.

Creating Automated Tests

Almost all the foundational pieces of infrastructure are now in place—a solution and project

structure, a basic domain model and LINQ to SQL repository system, an IoC container—so

now you can do the real job of writing application behavior and tests!

ProductsController currently produces a list of every product in your entire catalog. Let’s

improve on that: the first application behavior to test and code is producing a paged list of

products. In this section, you’ll see how to combine NUnit, Moq, and your component￾oriented architecture to design new application behaviors using unit tests, starting with that

paged list.

■Note TDD is not about testing, it’s about design (although it also takes care of some aspects of testing). With

TDD, you describe intended behaviors in the form of unit tests, so you can later run those tests and verify that

your implementation correctly satisfies the design. It allows you to decouple a design from its implementation,

creating a permanent record of design decisions that you can rapidly recheck against any future version of your

code base. “Test-driven development” is an unfortunate choice of name that misleads by putting the emphasis

on the word test. You might prefer the more up-to-date buzzphrase “Behavior-Driven Design (BDD)” instead,

though how that differs from TDD (if indeed it differs at all) is a topic for another debate.

102 CHAPTER 4 ■ SPORTSSTORE: A REAL APPLICATION

11. Windsor uses this IHttpModule to support PerWebRequestLifestyleModule, so that it can intercept the

Application_EndRequest event and dispose of anything it created during the request.

10078ch04.qxd 3/26/09 12:52 PM Page 102

Tải ngay đi em, còn do dự, trời tối mất!