asp.net-mvc中使用IOC容器創(chuàng)建控制器實例

1.)在使用IOC之前误甚,先談?wù)勈裁词荌OC?
IOC是Inversion of Control的縮寫-“控制反轉(zhuǎn)”宪萄。

解耦圖.png

通過上圖,由于引進了中間位置的第三方屎债,也就是IOC容器仅政,使得A、B盆驹、C圆丹、D這4個對象沒有了耦合的關(guān)系,所有的對象都由容器進行管理召娜,這樣也可以看出對象A獲得依賴對象B的過程运褪,由主動變成被動-(控制反轉(zhuǎn))惊楼。

2.)如何通過IOC容器創(chuàng)建實例玖瘸?
IOC容器是通過反射進行創(chuàng)建實例,而對IOC的具體實現(xiàn)的框架有多種檀咙,當然也可以自己封裝一套自己的容器雅倒,而今天主要介紹的是Unity容器。
通過NuGet導入Unity包:


Unity包.png

創(chuàng)建一個Unity容器:
IUnityContainer unityContainer = new UnityContainer();
注冊對象:
//IPhone-抽象
//AndroidPhone-具體實現(xiàn)
unityContainer.RegisterType<IPhone, AndroidPhone>();
獲取對象的實例:
IPhone phone = unityContainer.Resolve<IPhone>();

3.)Unity生命周期
默認瞬時生命周期:每次返回都是一個新的對象弧可。

container.RegisterType<AbstractPad, ApplePad>(new TransientLifetimeManager());
AbstractPad Pad1 = container.Resolve<AbstractPad>();
AbstractPad Pad2 = container.Resolve<AbstractPad>();
Console.WriteLine(object.ReferenceEquals(Pad1, Pad2));

單例生命周期:每次返回都是同一個對象蔑匣。

container.RegisterType<AbstractPad, ApplePad>(new SingletonLifetimeManager());
AbstractPad pad1 = container.Resolve<AbstractPad>();
AbstractPad pad2 = container.Resolve<AbstractPad>();
Console.WriteLine(object.ReferenceEquals(pad1, pad2));

線程單例生命周期:同一個線程就只有一個實例,不同線程就是不同實例。

container.RegisterType<AbstractPad, ApplePad>(new PerThreadLifetimeManager());
AbstractPad pad1 = null;
AbstractPad pad2 = null;
AbstractPad pad3 = null;
Action act1 = new Action(() =>
{
    pad1 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad1由線程id={Thread.CurrentThread.ManagedThreadId}");
});
var result1 = act1.BeginInvoke(null, null);

Action act2 = new Action(() =>
{
    pad2 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad2由線程id={Thread.CurrentThread.ManagedThreadId}");
});
var result2 = act2.BeginInvoke(t =>
{
    pad3 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad3由線程id={Thread.CurrentThread.ManagedThreadId}");
    Console.WriteLine($"object.ReferenceEquals(pad2, pad3)={object.ReferenceEquals(pad2, pad3)}");
}, null);
act1.EndInvoke(result1);
act2.EndInvoke(result2);
Console.WriteLine($"object.ReferenceEquals(pad1, pad2)={object.ReferenceEquals(pad1, pad2)}");

4.)Unity通過配置文件進行注冊
配置文件代碼:

 <unity>
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
    <containers>
      <container name="testContainer1">
        <!--支持AOP-->
        <extension type="Interception"/>
        <register type="IOC.Interface.IPhone,IOC.Interface" mapTo="IOC.Service.ApplePhone, IOC.Service"/>
        <!--是dll名稱裁良,不是命名空間-->
        <!--接口多個實現(xiàn)別名獲取-->
        <register type="IOC.Interface.IPhone,IOC.Interface" mapTo="IOC.Service.AndroidPhone, IOC.Service" name="Android">
          <!--別名--> 
          <interceptor type="InterfaceInterceptor"/>
          <interceptionBehavior type="Common.AOP.LogBeforeBehavior, Common"/>
          <interceptionBehavior type="Common.AOP.LogAfterBehavior, Common"/>
          <interceptionBehavior type="Common.AOP.ParameterCheckBehavior, Common"/>
          <lifetime type="transient" /> 
        </register>
        <register type="IOC.Interface.IMicrophone, IOC.Interface" mapTo="IOC.Service.Microphone, IOC.Service"/>
        <register type="IOC.Interface.IHeadphone, IOC.Interface" mapTo="IOC.Service.Headphone, IOC.Service"/>
        <register type="IOC.Interface.IPower, IOC.Interface" mapTo="IOC.Service.Power, IOC.Service"/>
        <register type="IOC.Interface.AbstractPad, IOC.Interface" mapTo="IOC.Service.ApplePad, IOC.Service"/>
        <register type="IOC.IDAL.IBaseDAL, IOC.IDAL" mapTo="IOC.DAL.BaseDAL, IOC.DAL"/>
        <register type="IOC.IBLL.IBaseBll, IOC.IBLL" mapTo="IOC.BLL.BaseBll, IOC.BLL">
          <constructor>
            <param name="baseDAL" type="IOC.IDAL.IBaseDAL, IOC.IDAL"  />
            <param name="id" type="System.Int32" value="3" />
          </constructor>
        </register>
        <register type="IOC.IDAL.IDBContext`1, IOC.IDAL" mapTo="IOC.DAL.DBContextDAL`1, IOC.DAL"/>
      </container>
    </containers>
  </unity>

前臺創(chuàng)建實例:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");//找配置文件的路徑
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, "testContainer1");
//創(chuàng)建實例
IPhone phone = container.Resolve<IPhone>("Android");

5.)基于Unity擴展AOP:AOP面向切面編程應(yīng)用場景

在有了以上了解之后凿将,在去通過IOC容器創(chuàng)建控制器實例便清晰了
有參控制器,通過容器創(chuàng)建并構(gòu)造函數(shù)依賴注入

 public class ThirdController : Controller
{
          public IUserService _iUserService = null;
          public ICompanyService _iCompanyService = null;

          public ThirdController(IUserService userService, ICompanyService companyService)
          { 
                     _iUserService = userService;
                     _iCompanyService = companyService; 
           }
}

1.)重寫“默認控制器工廠”

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
   {
        //要通過容器來創(chuàng)建控制器實例  得先得到容器
        //1. 獲取容器,并將后期依賴進行注冊
        IUnityContainer container = DIFactory.GetContainer();
        //2.通過容器創(chuàng)建控制器實例价脾,根據(jù)實例類型牧抵,查找實例構(gòu)造函數(shù)所需要的依賴項,
        //通過容器內(nèi)的對象進行注入侨把,若在容器內(nèi)無法找到則無法實例該對象
        return (IController)container.Resolve(t: controllerType);       
    }
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        return base.CreateController(requestContext, controllerName);
    }
}

2.)替換“默認控制器工廠”
Global.asax

  //用自定義的控制器工廠替換掉MVC框架中默認的控制器工廠
  ControllerBuilder.Current.SetControllerFactory(new RichardControllerFactory());

經(jīng)過上述的過程犀变,

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市秋柄,隨后出現(xiàn)的幾起案子获枝,更是在濱河造成了極大的恐慌,老刑警劉巖骇笔,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件省店,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜘拉,警方通過查閱死者的電腦和手機萨西,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旭旭,“玉大人谎脯,你說我怎么就攤上這事〕旨模” “怎么了源梭?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長稍味。 經(jīng)常有香客問我废麻,道長,這世上最難降的妖魔是什么模庐? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任烛愧,我火速辦了婚禮,結(jié)果婚禮上掂碱,老公的妹妹穿的比我還像新娘怜姿。我一直安慰自己,他們只是感情好疼燥,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布沧卢。 她就那樣靜靜地躺著,像睡著了一般醉者。 火紅的嫁衣襯著肌膚如雪但狭。 梳的紋絲不亂的頭發(fā)上披诗,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音立磁,去河邊找鬼呈队。 笑死,一個胖子當著我的面吹牛唱歧,可吹牛的內(nèi)容都是我干的掂咒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼迈喉,長吁一口氣:“原來是場噩夢啊……” “哼绍刮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挨摸,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤孩革,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后得运,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膝蜈,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年熔掺,在試婚紗的時候發(fā)現(xiàn)自己被綠了饱搏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡置逻,死狀恐怖推沸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情券坞,我是刑警寧澤鬓催,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站恨锚,受9級特大地震影響宇驾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜猴伶,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一课舍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧他挎,春花似錦筝尾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽栖忠。三九已至崔挖,卻和暖如春贸街,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狸相。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工薛匪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脓鹃。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓逸尖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瘸右。 傳聞我的和親對象是個殘疾皇子娇跟,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容