在上一个公司时,其中有一个项目就是以【通过反射获取所有实现接口的类】方式来实现程序的初始化。由于没人讲解(直接给项目代码),实现类写在好几处,处理的逻辑也更复杂(有调用顺序,是否允许继续,以及适用多个程序集等),无法直接查看引用和转到定义,所以费了些功夫才弄懂。
基本逻辑如参考
参考:秦林生 c# 通过反射获取所有实现接口的类,并且调用类中的公共方法
定义一个接口 IWork
namespace LchCommon.Model.Work
{
/// <summary>
/// 任务接口
/// </summary>
public interface IWork
{
#region 执行
/// <summary>
/// 执行
/// </summary>
/// <returns></returns>
bool Do();
#endregion
}
}
两个实现类
WorkA
namespace LchCommon.Model.Work
{
public class WorkA:IWork
{
//=================== construct function ==================
#region construct 任务A
/// <summary>
/// 任务A
/// </summary>
public WorkA()
{
}
#endregion
//=================== public properties ===================
#region 执行
/// <summary>
/// 执行
/// </summary>
/// <returns></returns>
public bool Do()
{
System.Diagnostics.Debug.WriteLine("WorkA");
return true;
}
#endregion
}
}
WorkB
namespace LchCommon.Model.Work
{
public class WorkB:IWork
{
//=================== construct function ==================
#region construct 任务B
/// <summary>
/// 任务A
/// </summary>
public WorkB()
{
}
#endregion
//=================== public properties ===================
#region 执行
/// <summary>
/// 执行
/// </summary>
/// <returns></returns>
public bool Do()
{
System.Diagnostics.Debug.WriteLine("WorkB");
return true;
}
#endregion
}
}
最好将接口和所有派生类,放在一起
实现调用逻辑
var _type = typeof(IWork);
var _list = new List<Type>();
var _ass = Assembly.GetAssembly(_type);//获取当前加载的程序集在其中定义指定的类型
var types = _ass.GetTypes();//获取此程序集中定义的类型
//遍历类型,找出接口IWork的实现类
foreach (var item in types)
{
if (item.IsInterface)
{
continue;
}
var _ins = item.GetInterfaces();//获取由当前[Type]实现或继承的所有接口
foreach (var ty in _ins)
{
if (ty == _type)
{
_list.Add(item);
}
}
}
object _obj,_result;
bool _next;
MethodInfo _method;
//调用实现接口的类中的公共方法
foreach (var item in _list)
{
_obj = Activator.CreateInstance(item);//使用指定类型的默认构造函数来创建该类型的实例
_method = item.GetMethod("Do");//搜索具有指定名称的公共方法
_result= _method.Invoke(_obj,null);//调用方法
_next = (bool)_result;
if (!_next)
{
break;
}
}