Get Property from a generic Object in C#

2019-01-19 07:40发布

have a look at this code please:

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;
}

When in write in Visual Studio "item.XXX" I should get the properties from my entitiy like .FirstName or .LastName. I do not know wether dataObjects is an IEnumerable or IOrder etc... it must be generic!

How can I get the real properties form item ? Only with Reflection?

4条回答
可以哭但决不认输i
2楼-- · 2019-01-19 08:12

Oded is right, it doesn't seem (to him or me) to make any sense to try and make this method generic. You are trying to genericize a method whose functionality is actually specific to a few types.

Now, that said, it seems the bulk of the function is independent of this property you want to access. So why not split it into two parts: that which can be genericized, and that which can't:

Something like this:

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;
}

Then your overloads dealing with specific types, e.g., IPerson, can reuse this code (which I suspect may be what you were after all along—code reuse):

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

...then for IOrder:

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

...and so on.

查看更多
霸刀☆藐视天下
3楼-- · 2019-01-19 08:12

Adding to Dan's answer, Func<T, TProperty> selector merely says that selector is an identifier for a method that takes in a parameter of type T and has a return type of TProperty. So, a valid method that could be passed into BindElements as a second parameter would be, for example,

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

In this case, TProperty would be a string and T would IPerson. You can then call BindElements like so

BindElements(myPersonCollection,CreatePersonElement);

where myPersonCollection can just be whatever List<T> you were referring to. Then moving on to the foreach loop

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 is being set to an object of type TProperty, which in the case of CreatePersonElement is a string. If a string doesn't work for you, just change the return type of the method to be whatever CreateElementContainer is accepting as its parameter.

You would then have one of these methods to pass into the second parameter for BindElements for each type you want to support (i.e. ICustomer, IOrder).

查看更多
爷、活的狠高调
4楼-- · 2019-01-19 08:18

If you add a constraint to the generic type (say it has to implement the IPerson interface), you can use any methods defined on the interface:

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

If IPerson defines FirstName and LastName peroperties, you can use them with T.

See the link for the different types of generic constraints possible.

查看更多
聊天终结者
5楼-- · 2019-01-19 08:34

I would read http://msdn.microsoft.com/en-us/library/d5x73970.aspx and think about Oded's answer again.

查看更多
登录 后发表回答