反射和特性的一些通用方法
直接上代码
1.基础类型 ClassData,存放类型数据
/// <summary>
/// 类的数据
/// <para>存入的是这个超类的下所有子类的类型数据</para>
/// <para>以直接继承为条件,抽象类再分一次</para>
/// </summary>
public sealed class ClassData
{
/// <summary>
/// 层级索引
/// </summary>
public int LayerIndex { get; set; }
/// <summary>
/// 当前类的类型
/// </summary>
public Type ClassType { get; set; }
/// <summary>
/// 当前类的父类
/// </summary>
public ClassData Father { get; set; }
/// <summary>
/// 所有再次抽象的类
/// </summary>
public List<ClassData> Children { get; set; } = new List<ClassData>();
/// <summary>
/// 当前类被直接继承的子类集合
/// </summary>
public List<Type> ChildrenTypes { get; set; }
}
核心方法,获取超类下的之间继承类
/// <summary>
/// 获取类型所有的直接继承的类型,对[抽象类]再递归获取
/// <para>使用的话:用递归,遍历<see cref="ClassData.ChildrenTypes"/> 判断<see cref="Type.IsAbstract"/>进行递归</para>
/// </summary>
/// <param name="target">目标对象</param>
/// <param name="inData"></param>
public static ClassData GetClassData<T>() where T : class
{
ClassData cd = new ClassData();
GetInheritors(typeof(T), ref cd);
return cd;
}
/// <summary>
/// 获取类型所有的直接继承的类型,对[抽象类]再递归获取
/// <para>使用的话:用递归,遍历<see cref="ClassData.ChildrenTypes"/> 判断<see cref="Type.IsAbstract"/>进行递归</para>
/// </summary>
/// <param name="target">目标对象</param>
/// <param name="inData"></param>
public static void GetInheritors(Type target, ref ClassData inData ,int layerindex =0)
{
if (inData == null) return;
//获取所有target的继承者,且只获取直接继承的类型
var types = target.Assembly.GetTypes()
.Where(a => target.IsAssignableFrom(a)
&& a != target
&& a.BaseType == target).ToList();
inData.LayerIndex += layerindex == 0 ? 1: layerindex;
inData.ClassType = target;
inData.Father = inData;
//获取直接继承的类
inData.ChildrenTypes = types.ToList();
//获取所有抽象的继承类型
var childrenType = types.Where(a => a.IsAbstract && a != target).ToList();
if (childrenType.Count == 0)
{
return;
}
else
{
foreach (var type in childrenType)
{
ClassData children = new ClassData()
{
Father = inData,
ClassType = type,
};
GetInheritors(type, ref children, inData.LayerIndex+1);
inData.Children.Add(children);
}
}
}
对类的创建
/// <summary>
/// 创建实例(FullName) 包括命名空间,但不包括程序集名称.
/// </summary>
/// <typeparam name="T">实例类型</typeparam>
/// <param name="fullName">实例的全名称</param>
/// <param name="para">对象实例参数</param>
/// <returns></returns>
public static T CreateObject<T>(string fullName, params object[] para) where T : class
{
try
{
var te = typeof(T).Assembly.GetTypes().Where(a => a.FullName == fullName).FirstOrDefault(); //反射入口
if (te == null)
{
throw new ArgumentNullException($" '{fullName}' 未找到实例!");
}
return Activator.CreateInstance(te, para) as T;//创建实例
}
catch(Exception ex)
{
throw ex;
}
}
/// <summary>
/// 创建实例, 类名(shortName),但是是T类型的子类,不包括抽象类
/// <para>建议使用这个<see cref="CreateObject"/></para>
/// </summary>
/// <typeparam name="T">超类</typeparam>
/// <param name="shortName">子类的类名(不包括抽象类)</param>
/// <param name="objects">构造参数</param>
/// <returns></returns>
public static T CreateObjectShortName<T>(string shortName, params object[] objects) where T : class
{
try
{
var result = typeof(T).Assembly.GetTypes()
.Where(a => !a.IsAbstract && a.Name == shortName).FirstOrDefault();
if (result == null)
{
throw new ArgumentNullException($"'{typeof(T).FullName}'未找到对应的名称'{shortName}'实现,实现是不包括抽象!");
}
return CreateObject<T>(result.FullName, objects);
}
catch (Exception ex)
{
throw ex;
}
}
使用实例:
以Listbox为例.获取Animal下的所有实现
public abstract class Animal
{
public string name;
public Animal(string name)
{
this.name = name;
}
public abstract void Eat();
}
public abstract class Dog : Animal
{
public Dog(string name) : base(name)
{
}
public override void Eat()
{
MessageBox.Show($"狗{name}嘴巴吃");
}
}
public abstract class Cat : Animal
{
protected Cat(string name) : base(name)
{
}
}
public class qqqqqqqCat : Cat
{
public qqqqqqqCat(string name) : base(name)
{
}
public override void Eat()
{
throw new NotImplementedException();
}
}
public class ddddddCat : Cat
{
public ddddddCat(string name) : base(name)
{
}
public override void Eat()
{
throw new NotImplementedException();
}
}
public class BigDog : Dog
{
public BigDog(string name) : base(name)
{
}
public override void Eat()
{
MessageBox.Show("大狗吃");
}
}
public class SmallDog : Dog
{
public SmallDog(string name) : base(name)
{
MessageBox.Show("小狗吃");
}
}
public abstract class CutDog : Dog
{
protected CutDog(string name) : base(name)
{
}
}
public class LLLLLLDog : CutDog
{
public LLLLLLDog(string name) : base(name)
{
}
}
public class bbbbbbbDog : CutDog
{
public bbbbbbbDog(string name) : base(name)
{
}
}
方法Create 是对ClassData的解析,
private void button2_Click(object sender, EventArgs e)
{
pAll.Controls.Clear();
var cd= Utility.Reflection.GetClassData<Animal>();
Create(cd);
}
Point location = new Point(5, 15);
public void Create(ClassData data)
{
if (data == null) return;
if (data.ChildrenTypes.Count == 0) return;
ListBox box1 = new ListBox();
box1.Name = data.ClassType.Name;
//box1.DropDownStyle = ComboBoxStyle.DropDownList;
box1.Location = location;
//创建这个类的所有直接实现的类型
foreach (var item in data.ChildrenTypes)
{
if (item.IsAbstract)
{
var reulst = data.Children.Where(a => a.ClassType == item).FirstOrDefault();
if (reulst != null)
{
location.X += 125;
Create(reulst);
}
}
box1.Items.Add($"{item.Name}{(item.IsAbstract ? "[abstract]" : "")}");
}
location.Y += box1.Height;
pAll.Controls.Add(box1);
}
运行效果
对超类直接继承的类,还有超类下面的超类再次解析是没有问题的;在dog中有三个直接继承者,其中还有一个抽象[CutDog],再去CutDog中找到两个继承者