如何移除未知类型Queue/List中的元素?(外部DLL私有成员场景)
解决外部DLL中私有嵌套结构体队列的运行时修改问题
针对你遇到的外部DLL中私有嵌套结构体队列无法直接修改的问题,核心障碍是无法在外部代码中直接引用私有结构体B的类型,导致无法直接转换List<object>为IEnumerable<B>。可以通过反射操作队列的构造函数或Enqueue方法完成修改,以下是具体实现:
方法一:通过反射调用Queue<T>的构造函数(推荐)
直接利用Queue<T>接收IEnumerable<T>的构造函数,通过反射传入修改后的列表:
A test = new A(); FieldInfo f = typeof(A).GetField("blah", BindingFlags.Instance | BindingFlags.NonPublic); object originalQueue = f.GetValue(test); // 将原队列转换为Object列表并修改 List<object> modifiedList = ((ICollection)originalQueue).Cast<object>().ToList(); modifiedList.RemoveAt(0); // 获取队列的实际类型(Queue<B>)以及元素类型(私有结构体B) Type queueType = f.FieldType; Type elementType = queueType.GetGenericArguments()[0]; // 获取Queue<T>接收IEnumerable<T>的构造函数 ConstructorInfo queueCtor = queueType.GetConstructor( new[] { typeof(IEnumerable<>).MakeGenericType(elementType) }); // 用修改后的列表创建新队列 object newQueue = queueCtor.Invoke(new object[] { modifiedList }); // 将新队列赋值回原字段 f.SetValue(test, newQueue);
方法二:通过反射调用Enqueue方法逐个添加元素
如果构造函数调用遇到问题,可以遍历修改后的列表,通过反射调用Enqueue方法添加到新队列中:
A test = new A(); FieldInfo f = typeof(A).GetField("blah", BindingFlags.Instance | BindingFlags.NonPublic); object originalQueue = f.GetValue(test); List<object> modifiedList = ((ICollection)originalQueue).Cast<object>().ToList(); modifiedList.RemoveAt(0); Type queueType = f.FieldType; Type elementType = queueType.GetGenericArguments()[0]; // 创建空队列 object newQueue = Activator.CreateInstance(queueType); // 获取Enqueue方法 MethodInfo enqueueMethod = queueType.GetMethod("Enqueue", new[] { elementType }); // 逐个添加修改后的元素 foreach (var item in modifiedList) { enqueueMethod.Invoke(newQueue, new object[] { item }); } f.SetValue(test, newQueue);
两种方法都通过反射绕过了私有类型的访问限制,无需直接引用私有结构体B即可完成队列的修改。
内容的提问来源于stack exchange,提问作者HiddenBabel
相关产品推荐
相关产品推荐

