日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.Net 应用框架设计系列(二)

發(fā)布時間:2024/6/14 asp.net 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .Net 应用框架设计系列(二) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

什么是一個好的設(shè)計?我想要做一個好的設(shè)計,有這么幾個挑戰(zhàn)。

1。對象的職責的定義和劃分

2。可擴展性

3。可重用性

1.?明確定義和劃分對象的職責。也就是說一個class,他應該專注于做很少的功能,而不是面面具到,無所不能。通過class的名稱和方法,我們可以很清楚這個class到底提供什么樣的功能和職責。說起來很簡單,可是實際做起來,還是很困難的。

2.?可擴展性。我的設(shè)計如何才可以做到,在需求發(fā)生變化后,在新的組件和服務產(chǎn)生后,我可以在不改動原有設(shè)計而把新的東西集成進來。在我替換和修改了已有組件的實現(xiàn)后,依賴他的上層的代碼不需要做任何的改動。

3.?可重用性。對象之間的依賴關(guān)系復雜。如和在一個新的項目里重用以前已經(jīng)實現(xiàn)的class,在我們現(xiàn)在的開發(fā)過程里,通常都是一個復雜的過程。

?

如果解決這三個難題呢。我認為,IOC為我們提供了解決這3個難題的途徑。

IOC,英文是Inversion of Control,中文翻譯為“控制反轉(zhuǎn)”。用于對調(diào)用和被調(diào)用者之間進行解耦。

首先我們從解耦這個方面來討論。

對組件之間的關(guān)系進行解耦,通常我們需要處理的情況有2種:1。獲取外部的配置信息 2。獲取一個組件對象的引用。舉個例子來說明一下:

using?System;
using?System.Configuration;

public?class?MyAwfulEmailClass
{
??
public?MyAwfulEmailClass()
??
{
??}

??
??
public?void?SendEmail(?String?from,?String?to,?String?message,?String?templateName?)
??
{
????String?host?
=?ConfigurationSettings.AppSettings["smtphost"];
????
int?port?=?Convert.ToInt(?ConfigurationSettings.AppSettings["smtpport"]?);

????NVelocityTemplateEngine?engine?
=?new?NVelocityTemplateEngine();
????String?newMessage?
=?engine.Process(?message,?templateName?);

????
//?Finally?send?message
??}

}

這是一個很簡單的類,只有寥寥數(shù)行的代碼。也許我們在自己的開發(fā)過程中,會經(jīng)??吹筋愃频拇a??墒蔷瓦@寥寥數(shù)行代碼里面,仍然有一些問題存在。

1.?代碼里是通過ConfigurationSettings來獲得配置信息。如果我們變更Configuration的存儲形式,或者用其他的xml文件存儲,或者是存儲在數(shù)據(jù)庫,或者是從遠端的webservice里獲得配置信息,代碼就不得不做出修改,重新編譯。

2.?class所擔負的職責要比他的名字所描述的要多。這個類提供發(fā)送郵件的功能,但是,不僅僅與此,這個類還會調(diào)用一個template 引擎對郵件的文本進行處理。由此帶來的另外一個問題就是,這個類必須具備對這個template 引擎的知識,知道如何調(diào)用這個引擎的方法。

這樣的2個主要問題帶來的影響就是,給這個類增加了兩個比較強的依賴關(guān)系。就是對外部config模塊和郵件template 引擎的依賴。也許有人會覺得,這沒有什么問題呀,我們平時寫代碼也是這樣的,沒有什么不好呀??墒亲屑毧紤]一下,如果需求變動,config部分變更,配置的Key發(fā)生變化,或者配置從另外的xml獲取,或者配置從Database獲取,或者配置是從一個webService獲取,那么上面的這段代碼無疑就要進行修改。如果這樣的地方多了,那修改起來既容易錯,又容易發(fā)生漏改。再說template引擎,如果我們換了另外一個模板引擎,我們也需要類似的做修改。

從另外一個角度說,如果我們又有了一個類似的項目,里面也有發(fā)郵件的功能。通常,最快的方法就是把這些代碼copy過來,做少量的修改。但是,這個并不是一個好的,高效的做飯。同時,代碼的維護也變得多出了一倍。這里,又引入了一個我們在框架設(shè)計是的一個思想,就是組件化,服務化。而IOC容器就提供了一種手段和工具來幫助我們管理這些組件和服務。

?

什么是組件呢?我個人認為,組件就是一小段可重用的代碼單元。對外部,他應該提供一個職責明確的服務接口,也就是說,這個組件只處理他職責范圍內(nèi)的事情,并且要處理得很好。通常來說,一個組件就是一個Class,實現(xiàn)了一個Service,也就是實現(xiàn)了一個interface。而這個interface就為我們引入了一個抽象層,把接口服務和實現(xiàn)分開。即我們常說的面向接口的開發(fā)。

再回到剛才的例子。

我們先定義Emailservice

//?The?contract
public?interface?IEmailSender
{
??
void?Send(String?from,?String?to,?String?message)
}

這個接口描述了發(fā)送Email這個Service的契約,只要實現(xiàn)了這個契約所規(guī)定的,不管是用smtp,還是IMAP或者其他的什么的,我們都認為是合法的。

OK,接下來我們給契約增加一個實現(xiàn),使用smpt來訪發(fā)送郵件。

//?The?implementation
public?class?SmtpEmailSender?:?IEmailSender
{
??
private?String?_host;
??
private?int?_port;

??
public?SmtpEmailSender(String?host,?int?port)
??
{
????_host?
=?host;
????_port?
=?port;
??}


??
public?void?Send(String?from,?String?to,?String?message)
??
{
????
//?Configures?the?Smtp?class?and?sends?the?e-mail
??}

}

看起來,是不是感覺這樣做好了一些?,F(xiàn)在這個類就只負責把郵件發(fā)送出去,并不負責對郵件的文本進行模板處理。

OK,我們再定義一個郵件Template的接口:

public?interface?ITemplateEngine
{
??String?Process(String?templateName)
}
光這樣一個ITemplateEngine還不夠,我們還需要一個組件來負責執(zhí)行模板轉(zhuǎn)換和分發(fā)郵件的功能。
public?interface?INewsletterService
{
??
void?Dispatch(String?from,?String[]?targets,?String?messageTypeName)
}

OK,現(xiàn)在讓我們來考慮一下INewsletterService接口服務應該如何實現(xiàn)。很顯然,需要使用IEmailSender 服務 ITemplateEngine 服務,而不用關(guān)系IEmailSenderITemplateEngine的具體實現(xiàn)是如何。

public?class?SimpleNewsletterService?:?INewsletterService
{
??
private?IEmailSender?_sender;
??
private?ITemplateEngine?_templateEngine;
??
??
public?SimpleNewsletterService(IEmailSender?sender,?
??????????????????????ITemplateEngine?templateEngine)
??
{
????_sender?
=?sender;
????_templateEngine?
=?templateEngine;
??}


??
public?void?Dispatch(String?from,?String[]?targets,?String?messageTypeName)
??
{
????String?message?
=?_templateEngine.Process(messageTypeName);

????
foreach(String?target?in?targets)
????
{
??????_sender.Send(from,?target,?message);
????}

??}

}

現(xiàn)在看上去,是不是感覺好了很多。通過設(shè)計上的重構(gòu),良好定義對象的職責,這段代碼已經(jīng)變得比以前更加靈活和易于擴展了。但是,仍然有個問題存在。我們需要自己把所有有關(guān)的東西聯(lián)系起來,包括IEmailSender, ITemplateEngine, 然后把他們傳遞到INewsletterService。

這些我們是可以手工通過代碼來完成,但是,借助于IOC容器,我們可以使用另外一種方式來完成同樣的功能。

接下來,我以.net下的開源IOC框架Castle為例子來說明IOC容器的神奇之處。

下面這段代碼,就可以完成我們上面的功能

IWindsorContainer?container?=?new?WindsorContainer();
container.AddComponent(?
"newsletter",?typeof(INewsletterService),?
????????????????????????
typeof(SimpleNewsletterService)?);
container.AddComponent(?
"smtpemailsender",?typeof(IEmailSender),?
????????????????????????
typeof(SmtpEmailSender)?);
container.AddComponent(?
"templateengine",?typeof(ITemplateEngine),?
????????????????????????
typeof(NVelocityTemplateEngine)?);

//?Ok,?start?the?show
INewsletterService?service?=?(INewsletterService)?container["newsletter"];
service.Dispatch(
"hammett?at?gmail?dot?com",?friendsList,?"merryxmas");

OK,讓我來解釋一下,上面的這段代碼里到底是如何發(fā)揮這神奇功效的。

1.???? 首先,在容器里注冊INewsletterService 服務,并指定服務的實現(xiàn)是SimpleNewsletterService,服務在容器內(nèi)的索引Keynewsletter

2.???? 在容器里注冊IEmailSender服務,并指定IEmailSender的實現(xiàn)是SmtpEmailSender,服務在容器內(nèi)的索引Keysmtpemailsender。容器會檢查SmtpEmailSender類,發(fā)現(xiàn)他只有一個帶參數(shù)的構(gòu)造函數(shù)SmtpEmailSender(String host, int port),而hostport目前還無法獲得,這個我們在后面會對SmtpEmailSender修改一下,來修正這個問題。

3.???? 在容器里注冊ITemplateEngine服務,并指定ITemplateEngine的實現(xiàn)是NVelocityTemplateEngine,服務在容器內(nèi)的索引Keytemplateengine

4.???? 容器檢測SimpleNewsletterService,發(fā)現(xiàn)他的構(gòu)造函數(shù)需要IEmailSenderITemplateEngine,容器會先創(chuàng)建 IEmailSenderITemplateEngine的實例,然后再創(chuàng)建出SimpleNewsletterService實例。

首先我們修改SmtpEmailSender的實現(xiàn),以適應容器。

public?class?SmtpEmailSender?:?IEmailSender
{
??
private?String?_host;
??
private?int?_port;

??
public?SmtpEmailSender()
??
{
????_host?
=?"mydefaulthost";
????_port?
=?110;?//?default?port
??}


??
public?String?Host
??
{
????
get?{?return?_host;?}
????
set?{?_host?=?value;?}
??}

??
??
public?int?Port
??
{
????
get?{?return?_port;?}
????
set?{?_port?=?value;?}
??}


??
//
}

如上所示,我們提供了一個無參數(shù)的構(gòu)造函數(shù),并且提供了兩個屬性HostPort。這樣容器可以創(chuàng)建一個SmtpEmailSender,并且通過讀取配置,來設(shè)置HostPort。

一個簡單的配置文件的例子如下:

<?xml?version="1.0"?encoding="utf-8"??>??

<configuration>?

????
<configSections>

????????
<section?name="castle"

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

????????????????Castle.Windsor"
?/>

????
</configSections>

?

????
<castle>

????????
<components>

????????????
<component?id="smtpemailsender">

????????????????
<parameters>

????????????????????
<host>localhost</host>

????????????????????
<port>110</port>

????????????????
</parameters>

????????????
</component>

????????
</components>

????
</castle>?

</configuration>

這樣,容器替我們完成了創(chuàng)建組件的任務。容器可以檢測容器內(nèi)的組件的相互依賴性,并且可以通過外部的配置文件來配置容器的實現(xiàn),設(shè)置其屬性。

本質(zhì)上來說,容器幫我們把組件之前的耦合性轉(zhuǎn)移到容器外的配置文件里。但是組件之間的依賴性是通過接口來弱化的,就只是一個松耦合的關(guān)系。

當然,容器的作用不僅僅與此,我們還可以為同一個服務指定多個實現(xiàn),通過配置,可以指定被依賴的服務采用何種實現(xiàn),可以為指定的組件定制自己ComponentActivator來控制其創(chuàng)建過程。還可以通過動態(tài)代理的方式,完成一些面向方面的特殊功能。

總之,IOC容器是非常強大的工具,是我們框架的基礎(chǔ)與核心,為框架的可擴充提供了必備的條件

轉(zhuǎn)載于:https://www.cnblogs.com/BlogNetSpace/archive/2012/03/20/1334174.html

總結(jié)

以上是生活随笔為你收集整理的.Net 应用框架设计系列(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。