C# 如何编写一个可以使用泛型从任何类输出数据的方法?

C# 如何编写一个可以使用泛型从任何类输出数据的方法?,c#,.net,generics,data-binding,C#,.net,Generics,Data Binding,我正在尝试编写一个自定义方法,以使用泛型填充ListView控件: private void BindDataToListView(List<T> containerItems) { this.View = View.Details; this.GridLines = true; this.FullRowSelect = true; if (this.Items.Count > 0)

我正在尝试编写一个自定义方法,以使用泛型填充ListView控件:

    private void BindDataToListView(List<T> containerItems)
    {
        this.View = View.Details;
        this.GridLines = true;
        this.FullRowSelect = true;

        if (this.Items.Count > 0)
            this.Items.Clear();

        this.BeginUpdate();

        int i = 0;
        foreach (T item in containerItems)
        {
            // do something
        }

        this.EndUpdate();
    }
private void BindDataToListView(列表容器项)
{
this.View=View.Details;
this.GridLines=true;
this.FullRowSelect=true;
如果(this.Items.Count>0)
this.Items.Clear();
this.BeginUpdate();
int i=0;
foreach(集装箱项目中的T项)
{
//做点什么
}
这个.EndUpdate();
}
参数containerItems可以有许多项,因为我使用的是泛型。但我陷入了foreach循环。如何访问containerItems中的值


我必须在foreach循环中的每个T实例上使用反射吗?我想我需要检索属性名。但是一旦我有了类型T的属性名,我如何检索该值呢?

您可以将T限制为一个接口,并在迭代中使用该接口。

如果列表中的项是完全不受约束的类型,那么您可以将它们简单地视为类型
object
。调用
GetType()
获取对象的类型。在此基础上,您可以调用
GetProperties()
来获取
PropertyInfo
对象的数组。对于这些属性,您可以调用
GetValue()
来检索属性的值

如果您已经知道某个属性的名称,只需调用
GetProperty()
即可检索该属性:

string valueAsString = item.GetType().GetProperty("Something")
                         .GetValue(item, null).ToString();

我不完全理解你的要求,但我认为这将为你指明正确的方向。请要求澄清,如果它看起来可以帮助,它是不清楚的

可以使用反射通过访问对象的给定属性

object o;
PropertyInfo info = o.GetType().GetProperty().GetProperty("NameOfPropertyIWant");
你可以通过

object value = info.GetValue(o, null);

现在,如果要访问不同类型对象上的同名属性,则应该考虑添加接口

public interface IHasThePropertyIWant {
    object NameOfPropertyIWant { get; }
}
然后你可以通过

void BindDataToListView(List<T> containerItems) where T : IHasThePropertyIWant

什么不代表什么?
就像现在一样,它是一个泛型类型,可以。。。什么都行

所以,我要做的是创建一个接口
IListViewBindable
或类似的东西。例如,该接口可以有一个方法“
CreateListViewItem

然后,我将更改该方法,以便对您的类型参数T应用一个约束,即T应该实现
IListViewBindable
,如下所示:

public void BindDataToListView<T>( List<T> containerItems ) where T : IListViewBindable
{}

最常见的方法(使用winforms)是通过
TypeDescriptor
;这允许您使用与类相同的东西
DataTable
;“完整”模式相当复杂(包括检查
IListSource
ITypedList
等;但是,短版本是;要获取可用属性:

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
要获取命名属性,请执行以下操作:

PropertDescriptor prop = props[propName];
要获取实例(
sourceObject
)的值,请执行以下操作:

要将值呈现为字符串(使用指定的转换器),请执行以下操作:

使用反射来完成您正试图执行的操作:使用反射来填充ListView。使用反射可以节省很多麻烦。它已经解决了您在这条路径上将遇到的所有棘手问题


如果你真的真的想自己做,Marc的答案(当然)是完全正确的。

这和做obj.GetType().GetProperty(“姓氏”).GetValue(obj,null)一样吗?不完全一样;重要的是,它考虑了自定义模型(通过(
TypeDescriptionProvider
)来获得完全支持(对于自定义
ITypedList
等)您需要额外的工作,但这意味着如果您确实需要支持它,您不必重写所有内容。它还将支持类似于HyperDescriptor的内容,而不做任何更改;-p
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
PropertDescriptor prop = props[propName];
object val = prop.GetValue(sourceObject);
string s = prop.Converter.ConvertToString(val);