使用反射获取构造的子类类型的集合
我想创建一个实现IEnumerable <T>的类,但是使用反射生成T,并通过IEnumerable <T>返回它们,其中T'是T的完全构造的子类,其中某些属性隐藏,而其他属性为只读。
好的,可能还不太清楚。让我通过我想拥有一个CollectionCollection <T>的代码媒介来解释这一点,如下所示:
public class CollectionView<T> : IEnumerable<T> { public CollectionView(IEnumerable<T> inputCollection, List<string> hiddenProperties, List<string> readonlyProperties) { // ... } // IEnumerable<T> implementation which returns a collection of T' where T':T. } ... public class SomeObject { public A { get; set; } public B { get; set; } public C { get; set; } } ... var hiddenProperties = new List<string>(new[] { "A" }); var readOnlyProperties = new List<string>(new[] { "C" }); IEnumerable<SomeObject> someObjects = CollectionView<SomeObject>(hiddenProperties, readOnlyProperties); ... dataGridView1.DataSource = someObjects;
(当显示在dataGridView1中时,显示列B和C,并且C具有只读的基础存储)
这是可能的/理想的,还是我完全失去了理智/这个问题是否表明了我作为程序员的严重不足?
我想这样做,这样我就可以操纵要传递到DataGridView中的集合,而不必直接操纵DataGridView来隐藏列/使列为只读。因此,没有"哦,只使用dataGridView1.Columns.Remove(blah)/ dataGridView1.Columns [blah] .ReadOnly = true"答案!!
帮助!
解决方案
Castle.DynamicProxy将完成此任务。
我们将要做的是创建一个继承T的拦截器。我们将存储隐藏和只读属性的集合。调用getter或者setter时,拦截器将检查该属性是否存在于任何一个集合中,然后采取适当的措施。
但是,我不知道我们将如何隐藏财产。我们不能在派生类中更改基类的访问修饰符。我们也许可以使用new
关键字,但是我不知道如何使用Castle.DynamicProxy来做到这一点。
我们甚至无法隐藏属性,即使创建子类的代理也是如此。我们至少可以动态地构造一个具有良好属性的不同类型,但它不是T。
但是,如果只需要使用数据绑定,那么返回一个对象列表就足够了。
我决定采取不同的方法来解决这个问题,我真的没有看到树木成树木!我决定创建一个扩展方法,将我的IEnumerable转换为数据表,然后可以根据需要传递该数据表:
public static DataTable ToDataTable<T>(this IEnumerable<T> collection) { DataTable ret = new DataTable(); Type type = typeof(T); foreach (PropertyInfo propertyInfo in type.GetProperties()) { // Ignore indexed properties. if (propertyInfo.GetIndexParameters().Length > 0) continue; ret.Columns.Add(propertyInfo.Name); } foreach (T data in collection) { DataRow row = ret.NewRow(); foreach (PropertyInfo propertyInfo in type.GetProperties()) { // Ignore indexed properties. if (propertyInfo.GetIndexParameters().Length > 0) continue; row[propertyInfo.Name] = propertyInfo.GetValue(data, null); } ret.Rows.Add(row); } return ret; }