我的开发框架(WinForm)3
今天继续给大家介绍核心库的IOC的使用,在我的框架里,IOC使用的比较简单,主要是用于解除模块间的耦合和实例化接口。
1、接口说明,IocContainer接口比较简单只有3个方法,但是是系统中用的最多的。
IocContainer
public interface IocContainer:IDisposable
{
/// <summary>
/// 获得某个接口的一组实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>IEnumerable{``0}.</returns>
IEnumerable<T> GetInstances<T>();
/// <summary>
/// 获取接口的一个实例
/// </summary>
/// <typeparam name="T">接口的类型</typeparam>
/// <returns>,如果没有注册该接口,则返回null</returns>
T GetInstance<T>();
/// <summary>
/// 根据关键字获取对象
/// </summary>
/// <param name="key">The key.</param>
/// <returns>System.Object.</returns>
object GetInstance(string key);
}
2、接口的实现。我用的是AutoFac,选用他基于2个方面的考虑,第一是对MEf和泛型的支持,第二是效率
园子里的Leepy 已经对比过主流的IOC框架,http://www.cnblogs.com/liping13599168/archive/2011/07/17/2108734.html,
时间比较早了,有兴趣的可以用最新的类库测试一下。
AutoFac有对MEF的扩展插件,很方便。这样做的好处是,我可以只在核心模块中引用AutoFac ,业务模块中无需引用,用Mef标示即可,对于团队开发来说,他无需再了解AutoFac如何使用。
不多说了,上代码
ContainerBuilder builder; IContainer _container = null; public AutofacContainer(params ComposablePartCatalog[] catalogs) { builder = new ContainerBuilder(); bool isRegisterOrm = false; foreach (var item in catalogs) { builder.RegisterComposablePartCatalog(item); if (item is DirectoryCatalog && !isRegisterOrm) { DirectoryCatalog dir=item as DirectoryCatalog; } } } 其中ComposablePartCatalog 是MEF的东东,ContainerBuilder 是AutoFac的东西, 这一步主要是讲Mef的组件注册到AutoFac里。然后通过 IContainer Container=builder.Build(Autofac.Builder.ContainerBuildOptions.IgnoreStartableComponents); 这个方法初始化完成,我测试的时候发现这个方法,只能执行一次,第二次就报错。
对应IocContainer.GetInstance 这个方法的实现就简单了,调用Autofac的对应的方法就行了
bool bl = Container.TryResolve<T>(out t);
返回t 就OK了,
需要注意的是,Mef对泛型支持的不太好,所以需要单独处理。
对于IRepository<T>和IRepository<T,Tid>接口来说,最理想的的情况是,我需要处理哪个实体类,就直接用var rep= IocContainer.GetInstance<IRepository<T>>() 这种方式,就能到IRepository<T>的实例,然后进行后面的操作了。
首先获得加载文件的所有 Assembly,然后判断他的名字是否以"Repository`1"结尾,然后调用AutoFac的泛型注册方法,注册,
Assembly ass = Assembly.LoadFile(filepath);由于本人对Autofac 也是一知半解,只能用笨办法,肯定有好的办法,只是我还不知道.望园子里的高手指点一下。
Type[] types = ass.GetTypes().Where(t => t.Name.EndsWith("Repository`1")).ToArray();
if (types.Length > 0 && types[0].Name != "IRepository`1")
{
builder.RegisterGeneric(types[0]).As(typeof(IRepository<>));
isload = true;
}
通过IocContainer接口,我们就可以创建并使用所有的接口了。
3、使用
在Core中我设计了一个全局静态类ApplicationEx,把IocContainer接口作为一个只读属性暴露出来,接口的实例化操作都在ApplicationEx的初始化中完成,在其他启动的时候,初始化ApplicationEx一次,保证IOC被初始化一次,后面所有模块的直接使用ApplicationEx的Container属性。这就达到了我们想要的目的。
4、扩展
我是一个比较懒的人,不想每次都写var rep= IocContainer.GetInstance<IRepository<T>>() ,觉得写得有点多
然后在Core里给IocContainer 增加了个扩展方法,
/// <summary> /// 获得数据操作仓库接口 /// </summary> /// <typeparam name="T">操作的实体类</typeparam> /// <returns>IRepository{``0}.</returns> public static IRepository<T> GetRepository<T>(this IocContainer ioc) where T : EntityBase, new() { return ioc.GetInstance<IRepository<T>>(); }
以后所有的模块调用就直接写var rep= IocContainer.GetRepository<T>(),又少写了10几个字符,呵呵呵。
今天就到这里吧,后面接着给大家介绍。
分类: .Net