前言
最近对Nop框架里面的引擎模块比较感兴趣,于是就研究了一下(nopCommerce_4.10_Source),发现里面写的东西相辅相成,不再赘述,这里重点记一下对ITypeFinder 类型查找器学习遇到一些收获进行记录
什么是反射?
反射是使用另外一种方法来调用获取应用程序或者程序组件的一些信息,这个应用程序可以是我们正在运行的也可以是还没有运行的,
只要是能够被.NET调用的文件都可以使用反射来获取文件的信息,
如我们众所周知的.dll、.exe、com组件等都可以使用反射来获取文件的信息,
同时也可以使用反射来调用这些组件或者程序。
上面这段是复制人家的
作者:zhang_xinxiu
来源:CSDN
原文:https://blog.csdn.net/zhang_xinxiu/article/details/19502575
版权声明:本文为博主原创文章,转载请附上博文链接!
什么是类型查找器?
类型查找器,顾名思义,就是查找对应类型的代码实现;
在Nop中所实现的类型查找器,主要是运用在 IOC中,
通过向类型查找器查找在当前域下的接口实现类,并通过IOC
将它们注入到容器中,实现控制反转
代码分析
梳理整体逻辑及大致思路
看别人的源码,首先要了解作者在写程序时候的设计思路,第一步是是从整体一个宏观全局去了解,然后往下再各个模块及去分析,在此,我就大胆的对类型查找器这一小块的代码进行一个思路梳理及分析:
首先是所写的几个方法函数,其中四个方法都是通过类型去查找相应的实现类,还有一个是获取需要查找的程序集,
/// <summary>
/// 根据类型查找对应的类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="isConcreteClass"></param>
/// <returns></returns>
IEnumerable<Type> ClassFindOfType<T>(bool isConcreteClass=true);
/// <summary>
/// 根据类型查找对应的类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="isConcreteClass"></param>
/// <returns></returns>
IEnumerable<Type> ClassFindOfType(Type typeForm, bool isConcreteClass = true);
/// <summary>
/// 根据类型查找对应的类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="isConcreteClass"></param>
/// <returns></returns>
IEnumerable<Type> ClassFindOfType<T>(IList<Assembly> assemblies, bool isConcreteClass = true);
/// <summary>
/// 根据类型查找对应的类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="isConcreteClass"></param>
/// <returns></returns>
IEnumerable<Type> ClassFindOfType(Type typeForm, IList<Assembly> assemblies, bool isConcreteClass = true);
/// <summary>
/// 获取程序集
/// </summary>
/// <returns></returns>
IList<Assembly> LoadAssemblies();
首先说获取程序集:
/// <summary>
/// 获取程序集
/// </summary>
/// <returns></returns>
public IList<Assembly> LoadAssemblies()
{
List<Assembly> assemblies = new List<Assembly>();
if (IsLoadAppDomainAssembly)
{
AddAssemblyInAppDomain(assemblies);
}
AddAssemblyInConfig(assemblies);
return assemblies;
}
在获取程序集的是是否对是否获取当前域下所有的程序集这一条件进行了判断
默认的情况下是true的;
然后如果获取所有程序集的话就会执行AddAssemblyInAppDomain(我自己重新写的代码,方法名和源码不一样,原谅我的渣渣英语) 这个私有方法
/// <summary>
/// 获取当前域的程序集
/// </summary>
/// <param name="assemblies"></param>
private void AddAssemblyInAppDomain(List<Assembly> assemblies)
{
Assembly[] assemblyArrary = App.GetAssemblies();
foreach (var assembly in assemblyArrary)
{
if (CheckProperty(assembly.FullName))
{
if (!assemblies.Contains(assembly))
{
assemblies.Add(assembly);
}
}
}
}
这个方法主要就是获取当前域下面所有程序及的。而CheckProperty()这个方法 主要是和需要跳过的一些程序集进行筛选,主要代码如下:
首先声明一个字段,里面记录需要跳过的程序集名称组成的正则,还有一个字段是记录需要的程序集,一般默认贪婪匹配所有的程序集
/// <summary>
/// 跳过的程序集名称
/// </summary>
public string SkipAssembliesName { get; set; } = "^ System |^ mscorlib |^ Microsoft |^ AjaxControlToolkit |^ Antlr3 |^ Autofac |^ AutoMapper |^ Castle |^ ComponentArt |^ CppCodeProvider |^ DotNetOpenAuth |^ EntityFramework |^ EPPlus |^ FluentValidation |^ ImageResizer |^ itextsharp |^ log4net |^ MaxMind |^ MbUnit |^ MiniProfiler |^ Mono.Math |^ MvcContrib |^ Newtonsoft |^ NHibernate |^ nunit |^ Org.Mentalis |^ PerlRegex |^ QuickGraph |^ Recaptcha |^ Remotion |^ RestSharp |^ Rhino |^ Telerik |^ Iesi |^ TestDriven |^ TestFu |^ UserAgentStringLibrary |^ VJSharpCodeProvider |^ WebActivator |^ WebDev |^ WebGrease |^ Quartz |^ Owin |^ Microsoft.Owin";
/// <summary>
/// 需要查询的程序集名称
/// </summary>
public string LoadAssembliesName { get; set; } = ".*";
然后看注释
/// <summary>
/// 对需要跳过的和需要获取的程序集进行对比
/// </summary>
/// <param name="FullName"></param>
/// <returns></returns>
private bool CheckProperty(string FullName)
{
return !CheckProperty(FullName, SkipAssembliesName) && CheckProperty(FullName, LoadAssembliesName);
}
/// <summary>
/// 对需要跳过的和需要获取的程序集进行对比
/// </summary>
/// <param name="FullName"></param>
/// <param name="LoadAssembliesName"></param>
/// <returns></returns>
private bool CheckProperty(string FullName, string LoadAssembliesName)
{
return Regex.IsMatch(FullName, LoadAssembliesName, RegexOptions.IgnoreCase|RegexOptions.Compiled);
}
当所有程序集都查找完毕以后就是这个方法的主要用途了,该方法首先主要就是用于,通过遍历获取到的程序集来对程序集所继承的类型逐个分析:
/// <summary>
/// 根据类型查询类
/// </summary>
/// <param name="typeForm"></param>
/// <param name="assemblies"></param>
/// <param name="isConcreteClass"></param>
/// <returns></returns>
public IEnumerable<Type> ClassFindOfType(Type typeForm, IList<Assembly> assemblies, bool isConcreteClass = true)
{
//首先实例化一个返回值
List<Type> typeResult = new List<Type>();
try
{
foreach (var assembly in assemblies)
{
Type[] typeArrary = null;
try
{
typeArrary = assembly.GetTypes();
}
catch (Exception)
{
if (!IsIgnoreError)
{
throw;
}
}
if (typeArrary == null)
{
continue;
}
foreach (var type in typeArrary)
{
if (typeForm.IsAssignableFrom(type) || type.IsGenericTypeDefinition && DoesTypeImplementOpenGeneric(type, typeForm))
{
if (isConcreteClass)
{
if (!type.IsAbstract&&!type.IsInterface)
{
typeResult.Add(type);
}
}
else
{
typeResult.Add(type);
}
}
}
}
return typeResult;
}
catch (Exception)
{
throw;
}
}
首先将 assignTypeFrom.IsAssignableFrom(t)作为条件进行判断,
这个方法所判断的就是 当前传入的类型是否与查找到的程序集的类型,同出一脉。
当这个方法判断过后
就会 判断 (assignTypeFrom.IsGenericTypeDefinition || DoesTypeImplementOpenGeneric(t, assignTypeFrom)) 这个条件,这个条件所实现的含义就是: 当前传入的类型是否可以构造其他泛型类型,而后通过私有方法:
private bool DoesTypeImplementOpenGeneric(Type type,Type typeForm)
{
//构造当前类型的泛型类型的Type对象。
Type typeDefinition = type.GetGenericTypeDefinition();
foreach (var interFaces in type.FindInterfaces((filter,objects)=>true,null))
{
if (interFaces.IsGenericType)
{
bool IsMatch = typeForm.IsAssignableFrom(interFaces);
return IsMatch;
}
}
return false;
}
从上面的方法可以看出,其实最后得到的就是当前查找到的类型所有所继承的类型是否与当前所传入的类型的泛型类型是否同出一脉。
当以上两个条件均为True的时候(源码是将他们全都是False情况下进行判断,然后跳出循环,我个人习惯是全都写成True进行下一步),这个时候开始判断我们需要的是否只是具体的实现类,如果只需要具体类,在进行是否是接口或者抽象类的判断然后添加到最初实例化的返回集合中;
结语
对于Nop框架本人也是刚开始进行深入的研究,奈何本人开发资历浅显,很多东西都不能明白,不能和当世的个为大神对比,只能一个人一步一个脚印往前走,希望如果哪位大神拨冗翻阅拙作希望给小子指出文章的不足,小子万分感激