您的位置:首页 > 其它

反射实现IOC功能

2013-09-15 20:15 162 查看

通过反射实现IOC功能

这段时间园子里有不少介绍IOC组件的文章,由于自己也一直在学习IOC的各种组件,及IOC的思想,常见的IOC组件很多:AutoFac、Ninject、Utity包括.NET自带的MEF等。由于今天周六,女朋友去加班了(也是一枚标准的程序媛,做java开发),闲来没事,自己就想着根据反射可以自己写一个简易的IOC组件。IOC组件说白了就是根据反射实例化对应的接口。废话不多说,开始说说我的解决方案。

1、项目结构图:



IOCTest为web MVC项目。

Common 通过配置文件实例化对应的接口

IBLL定义的接口

BLL实现接口

2、引用

IOCTest项目引用IBLL、Common项目,不能引用BLL项目,这样就使IOCTest项目只依赖接口。

BLL项目引用IBLL并实现接口

修改BLL项目dll生成路径,使其DLL生成到IOCTest项目的Bin目录下,如下图设置



3、下面我们来看具体的实现

(1)在IBLL层的IHelloWord.cs类中我们定义一个接口,代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IBLL
{
public  interface IHelloWord
{
string SayHello(string Name);
}
}


(2)BLL层实现接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IBLL;

namespace BLL
{
public class HelloWord:IHelloWord
{
#region IHelloWord 成员

public string SayHello(string Name)
{
return  "Hello_"+Name;
}

#endregion
}

}


(3)在IOCTest 项目的根目录Web.config下做如下配置(把HelloWord和IHelloWord对应起来):

<appSettings>
<add key="IBLL.IHelloWord" value="BLL,BLL.HelloWord"/>
</appSettings>

说明:
  key值为接口的全称(命名空间+类名),value值为实现接口的类,两部分组成,逗号前面为生成的dll名称,逗号后面为类名全称(命名空间+类名)。


(4)Common 项目的IOCReflecter.cs类根据配置文件获取对应接口的实例化对象,代码实现如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;
using System.Configuration;

namespace Common
{
public class IOCReflecter
{
private static Hashtable s_type=null;
static IOCReflecter()
{
s_type = new Hashtable();
}

public static T CreateIntance<T>()
{
Type t=typeof(T);//key
Type type = s_type[t] as Type;//value
if (type == null)
{
string[] AssemblyInfos = ConfigurationManager.AppSettings[t.FullName].Split(',');
type = Assembly.Load(AssemblyInfos[0]).GetType(AssemblyInfos[1]);
s_type.Add(t, type);
}
return (T)CreateObject(type) ;
}

/// <summary>
/// 根据typeName获取Type对象
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
public static Type GetType(string typeName)
{
if (string.IsNullOrWhiteSpace(typeName))
{
return null;
}
return Type.GetType(typeName);
}
/// <summary>
/// 获取对象
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
private static object CreateObject(Type t)
{
if (t == null)
{
return null;
}
//查找没有参数的构造函数
//如果需要初始化带参数的构造函数 t.GetConstructors() 获取所有的构造函数 ,it.GetParameters()获取构造函数所有的参数,
ConstructorInfo NonParameterConstructors= t.GetConstructors().Where(it=>it.GetParameters().Length==0).FirstOrDefault();
if (NonParameterConstructors == null)
{
throw new Exception( t.FullName+"必须有一个无参数或默认的构造函数");
}
//调用数构造函数创建对象
return t.InvokeMember(null, BindingFlags.CreateInstance, null, null, null);
}
}
}


(5)测试

在IOCTest项目Controllers中添加HomeController.cs文件,代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using IBLL;
using Common;

namespace IOCTest.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/

public ActionResult Index()
{
//获取实例化对象
IHelloWord hello = IOCReflecter.CreateIntance<IHelloWord>();
ViewBag.Message = hello.SayHello("eric");
return View();
}

}
}


@{
ViewBag.Title = "Index";
}

<h2>@ViewBag.Message </h2>


最后上一张截图:



到此结束,准备收拾收拾下楼去吃饭,下午去国家图书馆看书,后续把AutoFac、Ninject、Utity总结一下,感觉Ninject比较好用,有兴趣的同学可以研究一下。

每天学习一点点,每天进步一点点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: