AssemblyManager 程序集管理器
程序执行中使用反射对框架的搭建有着强大的影响,如何管理程序集方便使用反射获取类型操作对象是本文章的重点
1.AssemblyInfo
对于一个程序集这里使用一个AssemblyInfo对象进行管理
- Assembly :对应的程序集
- AssemblyTypeList :该程序集中所有对象的类型(包括接口、抽象类等)
- AssemblyTypeGroupList :一个key对应多个值的字典存储对应的接口对应的派生类(Key:某个接口类型,Value:继承这个接口的类对象类型)
public Assembly Assembly { get; private set; }
public readonly List<Type> AssemblyTypeList = new List<Type>();
public readonly OneToManyList<Type, Type> AssemblyTypeGroupList = new OneToManyList<Type, Type>();
完整的AssemblyInfo代码
public sealed class AssemblyInfo
{
public Assembly Assembly { get; private set; }
public readonly List<Type> AssemblyTypeList = new List<Type>();
public readonly OneToManyList<Type, Type> AssemblyTypeGroupList = new OneToManyList<Type, Type>();
public void Load(Assembly assembly)
{
Assembly = assembly;
Type[] assemblyTypes = Assembly.GetTypes();
foreach (Type type in assemblyTypes)
{
if (type.IsAbstract || type.IsInterface)
continue;
Type[] interfaces = type.GetInterfaces();
foreach (Type interfaceType in interfaces)
{
AssemblyTypeGroupList.Add(interfaceType, type);
}
}
AssemblyTypeList.AddRange(assemblyTypes);
}
public void UnLoad()
{
AssemblyTypeList.Clear();
AssemblyTypeGroupList.Clear();
}
}
2.AssemblyManager
三个事件(加载某个程序集事件、卸载某个程序集事件、重新加载某个程序集事件)
字典对应的是程序集名称(使用int)对应的程序集信息AssemblyInfo
public static event Action<int> OnLoadAssemblyEvent;
public static event Action<int> OnUnLoadAssemblyEvent;
public static event Action<int> OnReLoadAssemblyEvent;
private static Dictionary<int, AssemblyInfo> AssemblyList = new Dictionary<int, AssemblyInfo>();
主要方法加载某个程序集
public static void LoadAssembly(int assemblyName, Assembly assembly)
{
bool isReload = false;
if (!AssemblyList.TryGetValue(assemblyName, out AssemblyInfo assemblyInfo))
{
assemblyInfo = new AssemblyInfo();
AssemblyList.Add(assemblyName, assemblyInfo);
}
else
{
isReload = true;
assemblyInfo.UnLoad();
if (OnUnLoadAssemblyEvent != null)
{
OnUnLoadAssemblyEvent(assemblyName);
}
}
assemblyInfo.Load(assembly);
if (OnLoadAssemblyEvent != null)
{
OnLoadAssemblyEvent(assemblyName);
}
if (isReload && OnReLoadAssemblyEvent != null)
{
OnReLoadAssemblyEvent(assemblyName);
}
}
其余遍历程序集方法,根据不同的方式去遍历程序集
完整AssemblyManager代码
public static class AssemblyManager
{
public static event Action<int> OnLoadAssemblyEvent;
public static event Action<int> OnUnLoadAssemblyEvent;
public static event Action<int> OnReLoadAssemblyEvent;
private static Dictionary<int, AssemblyInfo> AssemblyList = new Dictionary<int, AssemblyInfo>();
public static void LoadAssembly(int assemblyName, Assembly assembly)
{
bool isReload = false;
if (!AssemblyList.TryGetValue(assemblyName, out AssemblyInfo assemblyInfo))
{
assemblyInfo = new AssemblyInfo();
AssemblyList.Add(assemblyName, assemblyInfo);
}
else
{
isReload = true;
assemblyInfo.UnLoad();
if (OnUnLoadAssemblyEvent != null)
{
OnUnLoadAssemblyEvent(assemblyName);
}
}
assemblyInfo.Load(assembly);
if (OnLoadAssemblyEvent != null)
{
OnLoadAssemblyEvent(assemblyName);
}
if (isReload && OnReLoadAssemblyEvent != null)
{
OnReLoadAssemblyEvent(assemblyName);
}
}
public static IEnumerable<int> ForeachAssemblyName()
{
foreach (int assemblyName in AssemblyList.Keys)
{
yield return assemblyName;
}
}
public static IEnumerable<Type> Foreach()
{
foreach (AssemblyInfo assemblyInfo in AssemblyList.Values)
{
foreach (Type type in assemblyInfo.AssemblyTypeList)
{
yield return type;
}
}
}
public static IEnumerable<Type> Foreach(int assemblyName)
{
if (!AssemblyList.TryGetValue(assemblyName, out AssemblyInfo assemblyInfo))
yield break;
foreach (Type type in assemblyInfo.AssemblyTypeList) { yield return type; }
}
public static IEnumerable<Type> Foreach(Type findType)
{
foreach (AssemblyInfo assemblyInfo in AssemblyList.Values)
{
if(!assemblyInfo.AssemblyTypeGroupList.TryGetValue(findType,out List<Type> assemblyLoad))
yield break;
foreach (Type type in assemblyLoad)
{
yield return type;
}
}
}
public static IEnumerable<Type> Foreach(int assemblyName, Type findType)
{
if (!AssemblyList.TryGetValue(assemblyName, out AssemblyInfo assemblyInfo))
yield break;
if(!assemblyInfo.AssemblyTypeGroupList.TryGetValue(findType,out List<Type> classList))
yield break;
foreach(Type type in classList)
yield return type;
}
public static Assembly GetAssembly(int assemblyName)
{
return !AssemblyList.TryGetValue(assemblyName, out AssemblyInfo assemblyInfo) ? null : assemblyInfo.Assembly;
}
public static void Dispose()
{
foreach (AssemblyInfo assemblyInfo in AssemblyList.Values)
{
assemblyInfo.UnLoad();
}
AssemblyList.Clear();
if(OnLoadAssemblyEvent != null)
{
foreach (var @delegate in OnLoadAssemblyEvent.GetInvocationList())
{
OnLoadAssemblyEvent -= @delegate as Action<int>;
}
}
if (OnUnLoadAssemblyEvent != null)
{
foreach (var @delegate in OnUnLoadAssemblyEvent.GetInvocationList())
{
OnUnLoadAssemblyEvent -= @delegate as Action<int>;
}
}
if (OnReLoadAssemblyEvent != null)
{
foreach (var @delegate in OnReLoadAssemblyEvent.GetInvocationList())
{
OnReLoadAssemblyEvent -= @delegate as Action<int>;
}
}
OnLoadAssemblyEvent = null;
OnUnLoadAssemblyEvent = null;
OnReLoadAssemblyEvent = null;
}
}
3.测试
准备测试的类和接口
public interface ITest1
{
}
public interface ITest2
{
}
public class TestClass0
{
}
public class TestClass1 : ITest1
{
}
public class TestClass2 : ITest2
{
}
public class TestClass3 : ITest1, ITest2
{
}
进行测试代码
public class Program
{
static void Main(string[] args)
{
AssemblyManager.OnLoadAssemblyEvent += (assemblyName) =>
{
Console.WriteLine($"加载程序集 : {assemblyName}");
};
AssemblyManager.OnReLoadAssemblyEvent += (assemblyName) =>
{
Console.WriteLine($"重新加载程序集 : {assemblyName}");
};
AssemblyManager.OnUnLoadAssemblyEvent += (assemblyName) =>
{
Console.WriteLine($"卸载程序集 : {assemblyName}");
};
AssemblyManager.LoadAssembly(1, typeof(Program).Assembly);
foreach (Type type in AssemblyManager.Foreach())
{
Console.WriteLine(type.FullName);
}
Console.WriteLine("=================================");
foreach (Type type in AssemblyManager.Foreach(1,typeof(ITest1)))
{
Console.WriteLine(type.FullName);
}
Console.WriteLine("=================================");
foreach (Type type in AssemblyManager.Foreach(1, typeof(ITest2)))
{
Console.WriteLine(type.FullName);
}
Console.ReadKey();
}
}
执行结果