c# - 反射 - 收集 WinForm 控件
问题描述
描述:我想从许多程序集中的 1000 多个 Winform 中获取所有可用的控件。我不想进行大量的重构工作。(小工具,原因是内部使用)
已经完成的事情:得到所有程序集,并从每个程序集中通过type.IsSubclassOf(selectedType)
.
主要项目的信息:许多类都有默认构造函数,有些没有,有些则引用其他基类。项目结构不是那么优化,因为它是一个开发超过 15 年的产品。
问题:我试图通过反射来进行所有控制,Activator.CreateInstance(type)
但是对于许多我采取了未处理的异常或其他无法管理的基类异常的类。我在此过程中遇到的另一个问题是铸造。我也尝试过FormatterServices.GetUninitializedObject(type)
,但我没有找到如何或是否可以进行控制。
问题:是否可以不费吹灰之力地收集具有这种结构的 winForm 'Form' 控件?实现这一目标的不同方法是什么?
代码示例
static List<AssemblyName> _assemblyList=new List<AssemblyName>();
static List<Type> _typeList = new List<Type>();
static List<Control> _controlList = new List<Control>();
private static void getFormTypes()
{
foreach (AssemblyName assemblyName in _assemblyList)
{
Assembly assembly = Assembly.Load(assemblyName);
foreach (Type type in assembly.GetTypes())
{
if (type.IsSubclassOf(typeof(Form)))
{
_typeList.Add(type);
}
}
}
}
private static void getAllControlsFromFormTypes()
{
foreach (Type type in _typeList)
{
object instance = default;
if (HasValidConstructor(type))
{
instance = Activator.CreateInstance(type);//Here I have unhandled exceptions from base classes during constructor invoking
GetValidControls((Control)instance);
}
}
}
private static void GetValidControls(Control container)
{
foreach (Control control in container.Controls)
{
GetValidControls(control);
if (!string.IsNullOrEmpty(control.Name) && !string.IsNullOrEmpty(control.Text))
{
_controlList.Add(control);
}
}
}
public static bool HasValidConstructor(Type t) => t.IsValueType || !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;```
解决方案
当您在窗体中放置一个控件时,设计器会为该控件创建一个成员字段。如果您没有更改GenerateMember
属性来更改此行为,或者没有使用创建没有成员变量的标签的数据表单向导,那么您可以使用这些成员字段获取所有控件,而无需实例化表单。
对于每个程序集,您无需以这种方式实例化即可获得表单和控件的列表:
IEnumerable<Type> GetFormsAndControlsTypes(Assembly assembly)
{
var forms = assembly.GetTypes()
.Where(type => typeof(Form).IsAssignableFrom(type));
var controls = forms.SelectMany(
form => form.GetFields(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(field => typeof(Control).IsAssignableFrom(field.FieldType))
.Select(field => field.FieldType));
return forms.Concat(controls).Distinct().ToList();
}
但是,通常此类任务看起来像代码分析而不是运行时任务。
推荐阅读
- ios - 如何强制 Xcode 在构建阶段运行运行脚本
- python - 错误:(-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow' while video streaming from Webcam
- c# - 如何在 WPF 中为文本框制作工具提示,使用 C# 而不是 XAML
- java - 是否存在具有“读取您的写入”保证和频繁更改数据的异步更新传播的嵌入式复制地图解决方案?
- python-3.x - 如何使用 Python 从 acoustID 获取曲目元数据
- gcc - VSCODE 的问题包括使用英特尔 IPP libarays
- python - 如何将列表/字符串中的单词数添加到计数器?
- reactjs - 不同生产版本的配置文件 React
- python - cv2 的自动完成功能在 vscode 中无法正常工作
- python - 用 PySpark 替换多个值