从C#中的通用对象获取属性

时间:2010-11-27 16:56:21

标签: c# object get properties generics

请看一下这段代码:

public void BindElements<T>(IEnumerable<T> dataObjects)
{
    Paragraph para = new Paragraph();

    foreach (T item in dataObjects)
    {
        InlineUIContainer uiContainer =
            this.CreateElementContainer(item.FirstName ????? )              
        para.Inlines.Add(uiContainer);
    }                         

    FlowDocument flowDoc = new FlowDocument(para);
    this.Document = flowDoc;
}

在Visual Studio中编写“item.XXX”时,我应该从我的权限中获取属性,如.FirstName或.LastName。我不知道数据对象是IEnumerable还是IOrder等......它必须是通用的!

如何获取真实属性表单项?只有反思?

4 个答案:

答案 0 :(得分:7)

Oded is right,对他或我来说似乎没有任何意义尝试使这个方法通用。您正在尝试对其功能实际上特定于几种类型的方法进行泛化。

现在,就是说,该函数的 bulk 似乎与您要访问的此属性无关。那么为什么不将它分成两部分:可以通用化的部分,以及不能部署的部分:

这样的事情:

void BindElements<T, TProperty>(IEnumerable<T> dataObjects,
                                Func<T, TProperty> selector)
{
    Paragraph para = new Paragraph();

    foreach (T item in dataObjects)
    {
       // Notice: by delegating the only type-specific aspect of this method
       // (the property) to (fittingly enough) a delegate, we are able to 
       // package MOST of the code in a reusable form.
       var property = selector(item);

       InlineUIContainer uiContainer = this.CreateElementContainer(property)
       para.Inlines.Add(uiContainer);
    }

    FlowDocument flowDoc = new FlowDocument(para);
    this.Document = flowDoc;
}

然后处理特定类型的重载(例如IPerson)可以重用此代码(我怀疑这可能是您在所有代码重用之后所使用的代码):

public void BindPeople(IEnumerable<IPerson> people)
{
    BindElements(people, p => p.FirstName);
}

...然后是IOrder

public void BindOrders(IEnumerable<IOrder> orders)
{
    BindElements(orders, o => p.OrderNumber);
}

......等等。

答案 1 :(得分:4)

如果向泛型类型添加constraint(比如必须实现IPerson接口),则可以使用界面上定义的任何方法:

public void BindElements<T>(IEnumerable<T> dataObjects) where T : IPerson

如果IPerson定义了FirstNameLastName个性能,您可以将它们与T一起使用。

请参阅可能的generic constraints种不同类型的链接。

答案 2 :(得分:3)

根据Dan的回答,Func<T, TProperty> selector只是说selector是一个方法的标识符,该方法接受T类型的参数并且返回类型为TProperty 。因此,可以作为第二个参数传递给BindElements的有效方法是,例如,

string CreatePersonElement(IPerson person) {
    return string.Format("{0} {1}", person.FirstName, person.LastName);
}

在这种情况下,TPropertystringTIPerson。然后,您可以像这样呼叫BindElements

BindElements(myPersonCollection,CreatePersonElement);

其中myPersonCollection可以是您所指的任何List<T>。然后继续前进到foreach循环

foreach (T item in dataObjects) {
   // Notice: by delegating the only type-specific aspect of this method
   // (the property) to (fittingly enough) a delegate, we are able to 
   // package MOST of the code in a reusable form.
   var property = selector(item);

   InlineUIContainer uiContainer = this.CreateElementContainer(property)
   para.Inlines.Add(uiContainer);
}

property被设置为TProperty类型的对象,在CreatePersonElement的情况下为string。如果string不适合您,只需将方法的返回类型更改为CreateElementContainer接受的任何参数。

然后,您可以将其中一种方法传递到BindElements的第二个参数,以支持您要支持的每种类型(例如ICustomerIOrder)。

答案 3 :(得分:0)

我会阅读http://msdn.microsoft.com/en-us/library/d5x73970.aspx并再次考虑Oded的答案。