学习kooboo的框架发现它的注入容器方法比较特别,同样是利用MVC的注入点,但它是查找网站下面bin所有的DLL利用反射查找特性找到对应的服务注入到容器。

这样的好处很简单:完全可以不用关心IOC容器是Ninject还是autofac 或者其它什么容器。 只要写上特性标记,再把对应的DLL拷贝到BIN下面,网站一启动就会自动注入到容器中。彻底进行解耦。

它的IOC注入步骤先后顺序:

1.程序集反射查找

2.IOC容器引擎初始化

3.利用特性注入IOC容器

4.MVC注入点注入

因为本人比较笨,理解东西比较差强人意,所以将以7篇文章分别介绍各个模块加强自己的理解:

IOC容器特性注入第一篇:程序集反射查找

IOC容器特性注入第二篇:初始引擎查找对应的IOC容器

IOC容器特性注入第三篇:Attribute封装

IOC容器特性注入第四篇:容器初始化

IOC容器特性注入第五篇:查找(Attribute)特性注入

IOC容器特性注入第六篇:利用MVC注入点,把容器启动

IOC容器特性注入第七篇:请求上下文作用域

源代码,我放在最后一篇,大家可以去下载。

我首先介绍下如何对网站BIN下面的DLL进行反射查找:

kooboo的程序集反射查找类就是Nop的三个封装类,分别是:

1.接口(ITypeFinder):

    public interface ITypeFinder {
IList<Assembly> GetAssemblies(); IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, bool onlyConcreteClasses = true); IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true); IEnumerable<Type> FindClassesOfType<T>(bool onlyConcreteClasses = true); IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true); IEnumerable<Type> FindClassesOfType<T, TAssemblyAttribute>(bool onlyConcreteClasses = true) where TAssemblyAttribute : Attribute; IEnumerable<Assembly> FindAssembliesWithAttribute<T>(); IEnumerable<Assembly> FindAssembliesWithAttribute<T>(IEnumerable<Assembly> assemblies); IEnumerable<Assembly> FindAssembliesWithAttribute<T>(DirectoryInfo assemblyPath);
}

2.应用程序实现类(AppDomainTypeFinder):

public class AppDomainTypeFinder : ITypeFinder {
#region Private Fields private bool loadAppDomainAssemblies = true; private string assemblySkipLoadingPattern = "^System|^mscorlib|^Microsoft|^CppCodeProvider|^VJSharpCodeProvider|^WebDev|^Castle|^Iesi|^log4net|^NHibernate|^nunit|^TestDriven|^MbUnit|^Rhino|^QuickGraph|^TestFu|^Telerik|^ComponentArt|^MvcContrib|^AjaxControlToolkit|^Antlr3|^Remotion|^Recaptcha|^DotNetOpenAuth,"; private string assemblyRestrictToLoadingPattern = ".*";
private IList<string> assemblyNames = new List<string>(); #endregion #region Constructors /// <summary>Creates a new instance of the AppDomainTypeFinder.</summary>
public AppDomainTypeFinder() {
} #endregion #region Properties /// <summary>The app domain to look for types in.</summary>
public virtual AppDomain App {
get { return AppDomain.CurrentDomain; }
} /// <summary>Gets or sets wether app should iterate assemblies in the app domain when loading types. Loading patterns are applied when loading these assemblies.</summary>
public bool LoadAppDomainAssemblies {
get { return loadAppDomainAssemblies; }
set { loadAppDomainAssemblies = value; }
} /// <summary>Gets or sets assemblies loaded a startup in addition to those loaded in the AppDomain.</summary>
public IList<string> AssemblyNames {
get { return assemblyNames; }
set { assemblyNames = value; }
} /// <summary>Gets the pattern for dlls that we know don't need to be investigated.</summary>
public string AssemblySkipLoadingPattern {
get { return assemblySkipLoadingPattern; }
set { assemblySkipLoadingPattern = value; }
} /// <summary>Gets or sets the pattern for dll that will be investigated. For ease of use this defaults to match all but to increase performance you might want to configure a pattern that includes assemblies and your own.</summary>
/// <remarks>If you change this so that assemblies arn't investigated (e.g. by not including something like "^MTA|..." you may break core functionality.</remarks>
public string AssemblyRestrictToLoadingPattern {
get { return assemblyRestrictToLoadingPattern; }
set { assemblyRestrictToLoadingPattern = value; }
} #endregion #region Internal Attributed Assembly class private class AttributedAssembly {
internal Assembly Assembly { get; set; }
internal Type PluginAttributeType { get; set; }
} #endregion #region ITypeFinder public IEnumerable<Type> FindClassesOfType<T>(bool onlyConcreteClasses = true) {
return FindClassesOfType(typeof(T), onlyConcreteClasses);
} public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, bool onlyConcreteClasses = true) {
return FindClassesOfType(assignTypeFrom, GetAssemblies(), onlyConcreteClasses);
} public IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true) {
return FindClassesOfType(typeof(T), assemblies, onlyConcreteClasses);
} public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true) {
var result = new List<Type>();
try {
foreach (var a in assemblies) {
foreach (var t in a.GetTypes()) {
if (assignTypeFrom.IsAssignableFrom(t) || (assignTypeFrom.IsGenericTypeDefinition && DoesTypeImplementOpenGeneric(t, assignTypeFrom))) {
if (!t.IsInterface) {
if (onlyConcreteClasses) {
if (t.IsClass && !t.IsAbstract) {
result.Add(t);
}
} else {
result.Add(t);
}
}
}
}
}
} catch (ReflectionTypeLoadException ex) {
var msg = string.Empty;
foreach (var e in ex.LoaderExceptions)
msg += e.Message + Environment.NewLine; var fail = new Exception(msg, ex);
Debug.WriteLine(fail.Message, fail); throw fail;
}
return result;
} public IEnumerable<Type> FindClassesOfType<T, TAssemblyAttribute>(bool onlyConcreteClasses = true) where TAssemblyAttribute : Attribute {
var found = FindAssembliesWithAttribute<TAssemblyAttribute>();
return FindClassesOfType<T>(found, onlyConcreteClasses);
} public IEnumerable<Assembly> FindAssembliesWithAttribute<T>() {
return FindAssembliesWithAttribute<T>(GetAssemblies());
} /// <summary>
/// Caches attributed assembly information so they don't have to be re-read
/// </summary>
private readonly List<AttributedAssembly> _attributedAssemblies = new List<AttributedAssembly>(); /// <summary>
/// Caches the assembly attributes that have been searched for
/// </summary>
private readonly List<Type> _assemblyAttributesSearched = new List<Type>(); public IEnumerable<Assembly> FindAssembliesWithAttribute<T>(IEnumerable<Assembly> assemblies) {
//check if we've already searched this assembly);)
if (!_assemblyAttributesSearched.Contains(typeof(T))) {
var foundAssemblies = (from assembly in assemblies
let customAttributes = assembly.GetCustomAttributes(typeof(T), false)
where customAttributes.Any()
select assembly).ToList();
//now update the cache
_assemblyAttributesSearched.Add(typeof(T));
foreach (var a in foundAssemblies) {
_attributedAssemblies.Add(new AttributedAssembly { Assembly = a, PluginAttributeType = typeof(T) });
}
} //We must do a ToList() here because it is required to be serializable when using other app domains.
return _attributedAssemblies
.Where(x => x.PluginAttributeType.Equals(typeof(T)))
.Select(x => x.Assembly)
.ToList();
} public IEnumerable<Assembly> FindAssembliesWithAttribute<T>(DirectoryInfo assemblyPath) {
var assemblies = (from f in Directory.GetFiles(assemblyPath.FullName, "*.dll")
select Assembly.LoadFrom(f)
into assembly
let customAttributes = assembly.GetCustomAttributes(typeof(T), false)
where customAttributes.Any()
select assembly).ToList();
return FindAssembliesWithAttribute<T>(assemblies);
} /// <summary>Gets tne assemblies related to the current implementation.</summary>
/// <returns>A list of assemblies that should be loaded by the factory.</returns>
public virtual IList<Assembly> GetAssemblies() {
var addedAssemblyNames = new List<string>();
var assemblies = new List<Assembly>(); if (LoadAppDomainAssemblies)
AddAssembliesInAppDomain(addedAssemblyNames, assemblies);
AddConfiguredAssemblies(addedAssemblyNames, assemblies); return assemblies;
} #endregion /// <summary>Iterates all assemblies in the AppDomain and if it's name matches the configured patterns add it to our list.</summary>
/// <param name="addedAssemblyNames"></param>
/// <param name="assemblies"></param>
private void AddAssembliesInAppDomain(List<string> addedAssemblyNames, List<Assembly> assemblies) {
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
if (Matches(assembly.FullName)) {
if (!addedAssemblyNames.Contains(assembly.FullName)) {
assemblies.Add(assembly);
addedAssemblyNames.Add(assembly.FullName);
}
}
}
} /// <summary>Adds specificly configured assemblies.</summary>
protected virtual void AddConfiguredAssemblies(List<string> addedAssemblyNames, List<Assembly> assemblies) {
foreach (string assemblyName in AssemblyNames) {
Assembly assembly = Assembly.Load(assemblyName);
if (!addedAssemblyNames.Contains(assembly.FullName)) {
assemblies.Add(assembly);
addedAssemblyNames.Add(assembly.FullName);
}
}
} /// <summary>Check if a dll is one of the shipped dlls that we know don't need to be investigated.</summary>
/// <param name="assemblyFullName">The name of the assembly to check.</param>
/// <returns>True if the assembly should be loaded into app.</returns>
public virtual bool Matches(string assemblyFullName) {
return !Matches(assemblyFullName, AssemblySkipLoadingPattern)
&& Matches(assemblyFullName, AssemblyRestrictToLoadingPattern);
} /// <summary>Check if a dll is one of the shipped dlls that we know don't need to be investigated.</summary>
/// <param name="assemblyFullName">The assembly name to match.</param>
/// <param name="pattern">The regular expression pattern to match against the assembly name.</param>
/// <returns>True if the pattern matches the assembly name.</returns>
protected virtual bool Matches(string assemblyFullName, string pattern) {
return Regex.IsMatch(assemblyFullName, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
} /// <summary>Makes sure matching assemblies in the supplied folder are loaded in the app domain.</summary>
/// <param name="directoryPath">The physical path to a directory containing dlls to load in the app domain.</param>
protected virtual void LoadMatchingAssemblies(string directoryPath) {
var loadedAssemblyNames = new List<string>();
foreach (Assembly a in GetAssemblies()) {
loadedAssemblyNames.Add(a.FullName);
} if (!Directory.Exists(directoryPath)) {
return;
} foreach (string dllPath in Directory.GetFiles(directoryPath, "*.dll")) {
try {
var an = AssemblyName.GetAssemblyName(dllPath);
if (Matches(an.FullName) && !loadedAssemblyNames.Contains(an.FullName)) {
App.Load(an);
} //old loading stuff
//Assembly a = Assembly.ReflectionOnlyLoadFrom(dllPath);
//if (Matches(a.FullName) && !loadedAssemblyNames.Contains(a.FullName))
//{
// App.Load(a.FullName);
//}
} catch (BadImageFormatException ex) {
Trace.TraceError(ex.ToString());
}
}
} protected virtual bool DoesTypeImplementOpenGeneric(Type type, Type openGeneric) {
try {
var genericTypeDefinition = openGeneric.GetGenericTypeDefinition();
foreach (var implementedInterface in type.FindInterfaces((objType, objCriteria) => true, null)) {
if (!implementedInterface.IsGenericType)
continue; var isMatch = genericTypeDefinition.IsAssignableFrom(implementedInterface.GetGenericTypeDefinition());
return isMatch;
}
return false;
} catch {
return false;
}
} }

3.web应用程序继承App作用域类(WebAppTypeFinder):

public class WebAppTypeFinder : AppDomainTypeFinder {
#region Fields private bool _ensureBinFolderAssembliesLoaded = true;
private bool _binFolderAssembliesLoaded = false; #endregion #region Ctor public WebAppTypeFinder() {
this._ensureBinFolderAssembliesLoaded = true;
} #endregion #region Properties /// <summary>
/// Gets or sets wether assemblies in the bin folder of the web application should be specificly checked for beeing loaded on application load. This is need in situations where plugins need to be loaded in the AppDomain after the application been reloaded.
/// </summary>
public bool EnsureBinFolderAssembliesLoaded {
get { return _ensureBinFolderAssembliesLoaded; }
set { _ensureBinFolderAssembliesLoaded = value; }
} #endregion #region Methods /// <summary>
/// Gets a physical disk path of \Bin directory
/// </summary>
/// <returns>The physical path. E.g. "c:\inetpub\wwwroot\bin"</returns>
public virtual string GetBinDirectory() {
if (HostingEnvironment.IsHosted) {
//hosted
return HttpRuntime.BinDirectory;
} else {
//not hosted. For example, run either in unit tests
return AppDomain.CurrentDomain.BaseDirectory;
}
} public override IList<Assembly> GetAssemblies() {
if (this.EnsureBinFolderAssembliesLoaded && !_binFolderAssembliesLoaded) {
_binFolderAssembliesLoaded = true;
string binPath = GetBinDirectory();
//binPath = _webHelper.MapPath("~/bin");
LoadMatchingAssemblies(binPath);
} return base.GetAssemblies();
}
#endregion
}
WebAppTypeFinder 这个类就可以对网站下面BIN文件夹所有的DLL文件进行反射查找程序集,可以根据类型 也可以跟特性查找,总之性能不错,大家可以拷贝代码 进行测试。

下一篇:

IOC容器特性注入第二篇:初始引擎查找对应的IOC容器

IOC容器特性注入第一篇:程序集反射查找的更多相关文章

  1. IOC容器特性注入第二篇:初始引擎查找对应的IOC容器

    上篇文章介绍了如何利用反射类查找网站bin文件夹下面所有DLL的程序集类,这篇文章将介绍如何初始化一个IOC容器引擎. 目前IOC容器有很多,如Ninject,Autofac等,每个容器的驱动都不一样 ...

  2. IOC容器特性注入第五篇:查找(Attribute)特性注入

    前面几篇文章分别介绍:程序集反射查找,特性,容器,但它们之间贯穿起来,形成查找Attribute注入IOC容器,就得需要下面这个类帮忙: 1.DependencyAttributeRegistrato ...

  3. IOC容器特性注入第四篇:容器初始化

    IOC容器,就是把各种服务都注入到容器里,想要什么就去拿什么,不仅解决服务类和接口类的耦合度还可以提高性能方便管理. 这里封装一个接口类和一个实现类 1.IContainerManager接口 pub ...

  4. IOC容器特性注入第三篇:Attribute封装

    Attribute(特性)=>就是对类,方法,字段的自定义属性的基类.可以利用Attribute对类,方法等进行自定义描述,方便区分. 既然如此,那我们就可以那些需要注入IOC容器和不需要注入I ...

  5. IOC容器特性注入第六篇:利用MVC注入点,把容器启动

    这里是利用MVC三个注入点中的:IDependencyResolver 进行注入 在全局类中Global.asax代码如下: #region MVC Inject System.Web.Mvc.Dep ...

  6. IOC容器特性注入第七篇:请求上下文作用域

    Ninject的对象作用域: Transient .InTransientScope() 每次调用创建新实例. Singleton .InSingletonScope() 单例,仅创建一个实例. Th ...

  7. SpringBoot启动流程分析(六):IoC容器依赖注入

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  8. Ioc容器依赖注入-Spring 源码系列(2)

    Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...

  9. Spring源码之IOC容器创建、BeanDefinition加载和注册和IOC容器依赖注入

    总结 在SpringApplication#createApplicationContext()执行时创建IOC容器,默认DefaultListableBeanFactory 在AbstractApp ...

随机推荐

  1. 【概念笔记】 EL表达式

    一.EL简介 1.语法结构  ${expression} 2.[]与.运算符  EL 提供.和[]两种运算符来存取数据. 当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要 ...

  2. [Xamarin] 製作Options Menu、Intent 呼叫網址和Market (转帖)

    Android的設計如果沒意外的話通常有三棵按鈕,BACK,HOME,OPTION (圖片來源:http://developer.android.com/design/index.html) 在OPT ...

  3. nginx lua整合安装

    安装lua JIT 下载 wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz 解压: tar zxvf LuaJIT-2.0.4.tar.gz 进入 ...

  4. LInux iptables学习

    作者原文 : http://blog.chinaunix.net/uid-9950859-id-98277.html       要在网上传输的数据会被分成许多小的数据包,我们一旦接通了网络,会有很多 ...

  5. C++ 模板与泛型编程

    <C++ Primer 4th>读书笔记 所谓泛型编程就是以独立于任何特定类型的方式编写代码.泛型编程与面向对象编程一样,都依赖于某种形式的多态性. 面向对象编程中的多态性在运行时应用于存 ...

  6. 酷派大神F2系列使用QPST进行nv备份和恢复,解决无信号问题(附备份文件)

    测试机器: 大神F2联通版 8675_W00 系统COOLUI55     写贴原因: 自己无意间刷错了包,结果手机无信号,进入工程模式怎么设置都没有用.尝试过系统还原(备份过).刷新的ROM.线刷, ...

  7. Atitit.并发测试解决方案(2) -----获取随机数据库记录 随机抽取数据 随机排序 原理and实现

    Atitit.并发测试解决方案(2) -----获取随机数据库记录 随机抽取数据 随机排序 1. 应用场景 1 2. 随机抽取数据原理 1 3. 常用的实现方法:::数据库随机函数 1 4. Mssq ...

  8. 啊哈C!思考快你一步——用编程轻松提升逻辑力

    啊哈C!思考快你一步——用编程轻松提升逻辑力(双色)(每个人都应该学习如何编程,因为它教会你如何思考.——史蒂夫.乔布斯) 啊哈磊著 ISBN 978-7-121-21336-6 2013年9月出版 ...

  9. log4qt的使用

    Log4Qt替换成新版本使其支持Qt5:https://github.com/devbean/log4qt/tree/master/src/log4qt 1. 解压log4qt到目标文件夹,如D:\Q ...

  10. asynchttpClient框架关于多文件批量上传的问题,改用xUtil

    RequestParams params = new RequestParams(); params.add("ordernum",ordernum); params.add(&q ...