NopCommerce为了支持插件功能,以及支持一些自动注册的功能。系统提供了类型查找器。ITypeFinder以及实现类就是提供此功能。通过类型查找器可以查找本程序域中的类,也可以查找整个bin目录下所有动态链接库中类,并把它们注册到类型反转容器中。ITypeFinder以及实现类如下:

ITypeFinder接口

/// <summary>
/// Classes implementing this interface provide information about types
/// to various services in the Nop engine.
/// </summary>
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);
}

FakeTypeFinder(模拟类型查找器)

 /// <summary>
/// 模拟类型查找
/// </summary>
public class FakeTypeFinder : ITypeFinder
{
public Assembly[] Assemblies { get; set; }
public Type[] Types { get; set; } public FakeTypeFinder(Assembly assembly, params Type[] types)
{
Assemblies = new[] { assembly };
this.Types = types;
}
public FakeTypeFinder(params Type[] types)
{
Assemblies = new Assembly[];
this.Types = types;
}
public FakeTypeFinder(params Assembly[] assemblies)
{
this.Assemblies = assemblies;
} public IList<Assembly> GetAssemblies()
{
return Assemblies.ToList();
} public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, bool onlyConcreteClasses = true)
{
return (from t in Types
where !t.IsInterface && assignTypeFrom.IsAssignableFrom(t) && (onlyConcreteClasses ? (t.IsClass && !t.IsAbstract) : true)
select t).ToList();
} public IEnumerable<Type> FindClassesOfType<T>(bool onlyConcreteClasses = true)
{
return FindClassesOfType(typeof(T), onlyConcreteClasses);
} public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true)
{
return FindClassesOfType(assignTypeFrom, onlyConcreteClasses);
} public IEnumerable<Type> FindClassesOfType<T>(IEnumerable<Assembly> assemblies, bool onlyConcreteClasses = true)
{
return FindClassesOfType(typeof(T), onlyConcreteClasses);
}
}
 #region FakeTypeFinder

        [TestMethod]
public void FakeTypeFinderTest()
{
var finder = new FakeTypeFinder(typeof(FakeClass));
var type = finder.FindClassesOfType<IFakeInterface>();
Assert.IsTrue(type.Any());
}
public interface IFakeInterface
{
}
public class FakeClass : IFakeInterface
{
} #endregion

AppDomainTypeFinder(应用程序类型查找器)

/// <summary>
/// A class that finds types needed by Nop by looping assemblies in the
/// currently executing AppDomain. Only assemblies whose names matches
/// certain patterns are investigated and an optional list of assemblies
/// referenced by <see cref="AssemblyNames"/> are always investigated.
/// </summary>
public class AppDomainTypeFinder : ITypeFinder
{
#region Fields private bool ignoreReflectionErrors = true;
private bool loadAppDomainAssemblies = true;
private string assemblySkipLoadingPattern = "^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";
private string assemblyRestrictToLoadingPattern = ".*";
private IList<string> assemblyNames = new List<string>(); #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 Nop should iterate assemblies in the app domain when loading Nop 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 Nop assemblies arn't investigated (e.g. by not including something like "^Nop|..." you may break core functionality.</remarks>
public string AssemblyRestrictToLoadingPattern
{
get { return assemblyRestrictToLoadingPattern; }
set { assemblyRestrictToLoadingPattern = value; }
} #endregion #region Methods 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)
{
Type[] types = null;
try
{
types = a.GetTypes();
}
catch
{
//Entity Framework 6 doesn't allow getting types (throws an exception)
if (!ignoreReflectionErrors)
{
throw;
}
}
if (types != null)
{
foreach (var t in types)
{
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;
} /// <summary>Gets the assemblies related to the current implementation.</summary>
/// <returns>A list of assemblies that should be loaded by the Nop 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 #region Utilities /// <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>
/// <param name="addedAssemblyNames"></param>
/// <param name="assemblies"></param>
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 Nop.
/// </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());
}
}
} /// <summary>
/// Does type implement generic?
/// </summary>
/// <param name="type"></param>
/// <param name="openGeneric"></param>
/// <returns></returns>
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;
}
} #endregion
}
 #region AppDomainTypeFinder

        public void AppDomainTypeFinderTest()
{
var finder = new AppDomainTypeFinder();
var type = finder.FindClassesOfType<IAppDomainInterface>();
type.Count();
typeof(IAppDomainInterface).IsAssignableFrom(type.FirstOrDefault());
} public interface IAppDomainInterface
{
}
public class AppDomainClass : IAppDomainInterface
{
} #endregion

在App或者单元测试中使用

WebAppTypeFinder(Web应用程序类型查找器)

/// <summary>
/// Provides information about types in the current web application.
/// Optionally this class can look at all assemblies in the bin folder.
/// </summary>
public class WebAppTypeFinder : AppDomainTypeFinder
{
#region Fields private bool _ensureBinFolderAssembliesLoaded = true;
private bool _binFolderAssembliesLoaded; #endregion #region Ctor public WebAppTypeFinder(NopConfig config)
{
this._ensureBinFolderAssembliesLoaded = config.DynamicDiscovery;
} #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;
} //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
}

继承自AppDomainTypeFinder。比AppDomainTypeFinder多支持了Web项目的类型查找

WebAppTypeFinder 这个类就可以对网站下面BIN文件夹所有的DLL文件进行反射查找程序集,可以根据类型 也可以跟特性查找,总之性能不错,大家可以拷贝代码 进行测试

http://www.cnblogs.com/miku/archive/2012/09/24/2700776.html

http://www.cnblogs.com/flyfish2012/p/3779810.html

类型查找器 ITypeFinder的更多相关文章

  1. 小米范工具系列之六:小米范 web查找器2.x版本发布

    小米范web查找器是一款快速识别端口及服务的小工具. 此工具使用java 1.8以上版本运行. 下载地址:http://pan.baidu.com/s/1c1NDSVe  文件名web finder ...

  2. jQuery源码分析系列(36) : Ajax - 类型转化器

    什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...

  3. 答:SQLServer DBA 三十问之一: char、varchar、nvarchar之间的区别(包括用途和空间占用);xml类型查找某个节点的数据有哪些方法,哪个效率高;使用存储 过程和使用T-SQL查询数据有啥不一样;

    http://www.cnblogs.com/fygh/archive/2011/10/18/2216166.html 1. char.varchar.nvarchar之间的区别(包括用途和空间占用) ...

  4. spring的PathMatchingResourcePatternResolver-通配符的Resource查找器

    PathMatchingResourcePatternResolver是一个通配符的Resource查找器,包括: /WEB-INF/*-context.xml com/mycompany/**/ap ...

  5. SpringMVC09异常处理和类型转化器

    public class User { private String name; private Integer age; public String getName() { return name; ...

  6. openEntityForm时候如何给关于(regardingobjectid)类型查找字段赋值?

    本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复264或者20170924可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me ...

  7. openEntityForm如何给关于(regardingobjectid)类型查找字段赋值?

    本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复264或者20170924可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me ...

  8. 资源查找器PathMatchingResourcePatternResolver的使用

    资源查找器PathMatchingResourcePatternResolver的使用 PathMatchingResourcePatternResolver是一个Ant通配符模式的Resource查 ...

  9. AI工具(缩放工具)(路径查找器)(旋转工具)(镜像工具)5.12

    缩放工具:选择图形,点击工具栏缩放工具,”ENTER"输入缩放比例,“复制”完成缩放复制. 路径查找器:选择两个图形,“窗口”“路径查找器”“差集”:大圆减去小圆,留下圆环. “减去顶层”: ...

随机推荐

  1. [原创]谷歌插件 - YE搜图助手(YeImageFinder)

    最新版本:下载 版本:v1.5 更新时间:2014年10月08日  +完善了:YeImageFinder:支持在每次启用插件时,也能正常绑定右键! +完善了:每次做完动作后,就马上关闭自身! 版本:v ...

  2. linux中的livecd、liveDVD和其他安装方式简介

    下载了几种不同格式的centos版本的iso文件,从而对比下各种iso文件的差别,下载的内容如下: 下载之后,分别在虚拟机中进行安装,从而查看有何区别: 1. 使用LiveCD进行安装 在选择安装介质 ...

  3. sensor BMA250源代码执行分析

    重力传感器是根据压电效应的原理来工作的.   所谓的压电效应就是 “对于不存在对称中心的异极晶体加在晶体上的外力除了使晶体发生形变以外,还将改变晶体的极化状态,在晶体内部建立电场,这种由于机械力作用使 ...

  4. 机器学习真的可以起作用吗?(2)(以二维PLA算法为例)

    一个问题:大多数情况下,M(hypothesis set的大小)是无穷大的,例如PLA算法.那么是不是我们的原则1就不能使用了? 我们试着做一些努力: Step1:寻找hypothesis set的e ...

  5. bzoj 2555 SubString(SAM+LCT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2555 [题意] 给定一个字符串,可以随时插入字符串,提供查询s在其中作为连续子串的出现 ...

  6. list、tuple、dict、set、map

    list Python内置的一种数据类型是列表. list是一种有序的集合,可以随时添加和删除其中的元素. # 创建list classmate = ['micheal', 'Bob', 'Tracy ...

  7. java的Socket通信例子及关于java.net.SocketException: Socket is closed错误

    今天写socket数据相互通信的时候,碰到一个及其蛋疼的错误.单向传输数据的时候server与client是没有问题的,但是两个都有输入输出操作的时候就出现了这个问题 java.net.SocketE ...

  8. Hadoop port to Jxta P2P Framework

    https://www.java.net/forum/topic/jxta/jxta-community-forum/hadoop-port-jxta-p2p-framework —————————— ...

  9. FrameWork 建模时查询项的usage

    § Identifier:代表被用于分组或汇总与其相关的Fact数据的列.也代表一个索引列.还代表日期或时间列.§ Fact:代表一个包含数值数据可被分组或汇总的列,例如,产品成本.§ Attribu ...

  10. HDU4570----Multi-bit Trie----简单的DP

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4570 题目意思: 给你N个数 要你分成多段,每段长度不能超过20 是的sum(ai*(2^bi))最小 ...