C# 从C中的泛型对象获取属性#

C# 从C中的泛型对象获取属性#,c#,object,get,properties,generics,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.FirstN

请查看此代码:

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;
}
public void BindElements(IEnumerable数据对象)
{
段落段落=新段落();
foreach(数据对象中的T项)
{
InlineUIContainer-uiContainer=
此.CreateElementContainer(item.FirstName?????)
段落Inlines.Add(uiContainer);
}                         
FlowDocument flowDoc=新的FlowDocument(段落);
此.Document=flowDoc;
}
在Visual Studio中编写“item.XXX”时,我应该从我的实体获取属性,如.FirstName或.LastName。我不知道dataObjects是IEnumerable还是IOrder等等。。。它必须是通用的

如何获取“真实属性”表单项?仅使用反射?

如果您向泛型类型中添加了一个(比如它必须实现
IPerson
接口),则可以使用接口上定义的任何方法:

public void BindElements<T>(IEnumerable<T> dataObjects) where T : IPerson
public void BindElements(IEnumerable数据对象),其中T:IPerson
如果
IPerson
定义了
FirstName
LastName
属性,则可以将它们与
T
一起使用

查看不同类型的可能方法的链接。

我会再次阅读并思考Oded的答案。

,尝试将此方法通用化(对他或我而言)似乎没有任何意义。您正在尝试泛化一个方法,该方法的功能实际上特定于一些类型

这就是说,函数的大部分似乎独立于您想要访问的属性。那么,为什么不将其分为两部分:可以泛化的部分和不能泛化的部分:

大概是这样的:

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;
}
…然后对于
IOrder

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

…等等。

除了Dan的答案之外,
Func selector
只是说
selector
是一个方法的标识符,该方法接受类型为
T
的参数,返回类型为
TProperty
。因此,可以作为第二个参数传递到
BindElements
的有效方法是

string CreatePersonElement(IPerson person) {
    return string.Format("{0} {1}", person.FirstName, person.LastName);
}
在这种情况下,
T属性
将是一个
字符串
T
将是
IPerson
。然后可以像这样调用
BindElements

BindElements(myPersonCollection,CreatePersonElement);
myPersonCollection可以是您所指的任何
List
。然后转到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
的情况下,它是一个
字符串。如果
字符串
不适用于您,只需将方法的返回类型更改为
CreateElementContainer
接受作为其参数的内容即可


然后,您可以使用这些方法中的一种,为要支持的每种类型(即
iccustomer
IOrder
)的
BindElements
传递第二个参数。

请告诉我。我的答案几乎是一样的。@Oded很抱歉混淆了它不应该意味着…是一个IEnumerable它应该意味着ICustomer或IOrder等。。。但你几乎已经得到了。。。问题是我不能把IPerson放在那里,因为那样会破坏该方法的通用功能!公开public BindElements方法的UserControl的用户正在传递一个列表,或者IEnumerable,T可以是IPerson、ICCustomer或IOrder,你明白了吗?@Lisa-但是如果想要有特定的方法来调用你的泛型参数,你已经“破坏”了函数的泛型性质。请解释为什么几个重载不能比一个bastardized泛型函数更好地工作?@Oded她的bastardized泛型函数无论如何都不能工作,如果不同的实体没有FirstName属性,反射与否。@siride-很清楚这一点。这就是为什么我首先质疑通用方法。我认为它比public void BindElements(object dataObjects)好,因为我必须进行强制转换…啊,我想我已经对此发表了评论,我现在这样做了…:@Dan Tao=>如果我想传递两个“选择器”,比如FirstName和LastName,该怎么办,BindElements方法参数将如何更改?我从来没有读过这个TProperty+选择器,也没有真正理解它;-)刚刚开始做真正通用的东西。+1-肯定是一个很好的实现,我在想,Func可能是她元素容器创建的某种工厂方法。不是按位解决方案,但值得一提:P感谢示例!不客气-是的,丹的解决方案确实值得称赞=)
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);
}