How can I get a value of a property from an anonymous type?
Asked Answered
B

12

29

I have a datagrid populated by a Linq query. When the focused row in the datagrid changes I need to set a variable equal to one of the properties in that object.

I tried...

var selectedObject = view.GetRow(rowHandle);
_selectedId = selectedObject.Id;

... but the compiler doesn't care for this at all ("Embedded statement cannot be a declaration or labled statement").

It seems like the property should be easy to access. Inspecting the object during runtime shows all the properties I expect, I just don't know how to access them.

How can I get access to the anonymous object's property?

Edit for Clarifications:

I happen to be using DevExpress XtraGrid control. I loaded this control with a Linq query which was composed of several different objects, therefore making the data not really conforming with any one class I already have (ie, I cannot cast this to anything).

I'm using .NET 3.5.

When I view the results of the view.GetRow(rowHandle) method I get an anonymous type that looks like this:

{ ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }

My objective is to get the ClientId from this anonymous type so I can do other things (such as a load a form with that client record in it).

I tried a couple of the suggestions in the early answers but was unable to get to a point where I could get this ClientId.

Blowbyblow answered 17/5, 2009 at 14:35 Comment(2)
What is the exact type of the identifier "view"?Kirschner
"View" is a GridView control from DevExpress.Blowbyblow
V
62

Have you ever tried to use reflection? Here's a sample code snippet:

// use reflection to retrieve the values of the following anonymous type
var obj = new { ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }; 
System.Type type = obj.GetType(); 
int clientid = (int)type.GetProperty("ClientId").GetValue(obj, null);
string clientname = (string)type.GetProperty("ClientName").GetValue(obj, null);

// use the retrieved values for whatever you want...
Viscose answered 28/7, 2010 at 23:33 Comment(4)
Thanks abdoul, your code is pretty easy to understand. I recently had a problem getting anonymous type and here:#3535469 I left the question. After some searching and working on the weekend I came to this page and it really made my day.Genagenappe
That's exactly why I love SOPhotoneutron
Really, too awesome answer! This is what i was searching from 2 weeks! Thank a lot!Onder
@ogborstad Done. The answer JaredPar provided was most accurate at the time I responded. This answer came along 12 months later and I agree, it is more accurate. (Only took me 7 years to notice.)Blowbyblow
E
24

A generic solution for getting the value of a data item for a given key

public static T GetValueFromAnonymousType<T>( object dataitem, string itemkey ) {
    System.Type type = dataitem.GetType();
    T itemvalue = (T)type.GetProperty(itemkey).GetValue(dataitem, null);
    return itemvalue;
}

Example:

var dataitem = /* Some value here */;
bool ismember = TypeUtils.GetValueFromAnonymousType<bool>(dataitem, "IsMember");
Enslave answered 4/12, 2010 at 2:25 Comment(1)
I found this solution to be the next best to declaring the anonymous types. Thanks.Anthropoid
U
17

One of the problems with anonymous types is that it's difficult to use them between functions. There is no way to "name" an anonymous type and hence it's very difficult to cast between them. This prevents them from being used as the type expression for anything that appears in metadata and is user defined.

I can't tell exactly which API you are using above. However it's not possible for the API to return a strongly typed anonymous type so my guess in that selectedObject is typed to object. C# 3.0 and below does not support dynamic access so you will be unable to access the property Id even if it is available at runtime.

You will need to one of the following to get around this

  • Use reflection to grab the property
  • Create a full type and use that to populate the datagrid
  • Use one of the many hacky anonymous type casts

EDIT

Here's a sample on how to do a hack anonymous type cast

public T AnonymousTypeCast<T>(object anonymous, T typeExpression) { 
  return (T)anonymous;
}

...
object obj = GetSomeAnonymousType();
var at = AnonymousTypeCast(obj, new { Name = String.Empty, Id = 0 });

The reason it's hacky is that it's very easy to break this. For example in the method where the anonymous type is originally created. If I add another property to the type there the code above will compile but fail at runtime.

Unshroud answered 17/5, 2009 at 14:46 Comment(3)
"hacky anonymous type casts" what are those?Kirschner
@AnthonyWJones, I added an example of a hacky anonymous type castUnshroud
Thank you for this answer. A very nice and elegant solution. It has only one drawback: It does not work if the anonymous object comes from another assembly. This is one reason why you should never ever return an anonymous object from a method, but not everyone knows that and so I have to deal with a library that unfortunately does exactly this.Snag
V
17

You could use the dynamic type to access properties of anonymous types at runtime without using reflection.

var aType = new { id = 1, name = "Hello World!" };
//...
//...
dynamic x = aType;
Console.WriteLine(x.name); // Produces: Hello World!

Read more about dynamic type here: http://msdn.microsoft.com/en-us/library/dd264736.aspx

Vasoconstrictor answered 30/3, 2012 at 7:4 Comment(1)
So simple and elegant I feel ashamed of not thinking of it :)Endoblast
R
3

When I was working with passing around anonymous types and trying to recast them I ultimately found it easier to write a wrapper that handled working with the object. Here is a link to a blog post about it.

http://somewebguy.wordpress.com/2009/05/29/anonymous-types-round-two/

Ultimately, your code would look something like this.

//create an anonymous type
var something = new {  
  name = "Mark",  
  age = 50  
};  
AnonymousType type = new AnonymousType(something);

//then access values by their property name and type
type.With((string name, int age) => {  
  Console.Write("{0} :: {1}", name, age);  
}); 

//or just single values
int value = type.Get<int>("age");   
Raasch answered 29/5, 2009 at 16:25 Comment(0)
M
1

As JaredPar guessed correctly, the return type of GetRow() is object. When working with the DevExpress grid, you could extract the desired value like this:

int clientId = (int)gridView.GetRowCellValue(rowHandle, "ClientId");

This approach has similar downsides like the "hacky anonymous type casts" described before: You need a magic string for identifying the column plus a type cast from object to int.

Monorail answered 17/5, 2009 at 16:49 Comment(0)
B
1

DevExpress's xtraGridView has a method like this GetRowCellDisplayText(int rowHandle, GridColumn column). With this method, the following code returns the id from the anonymous type.

var _selectedId = view.GetRowCellDisplayText(rowHandle, "Id");

Though this does not provide an answer to the question "How can I get access to the anonymous object's property?", it still attempts to solve the root cause of the problem.

I tried this with devXpress version 11.1 and I can see that the question was first asked almost 2.5 years ago. Possibly the author of the question might have got an workaround or found the solution himself. Yet, I am still answering so that it might help someone.

Brinkema answered 28/12, 2011 at 5:29 Comment(0)
C
0

This may be wrong (you may not have enough code there) but don't you need to index into the row so you choose which column you want? Or if "Id" is the column you want, you should be doing something like this:

var selectedObject = view.GetRow(rowHandle);
_selectedId = selectedObject["Id"];

This is how I'd grab the contents of a column in a datagrid. Now if the column itself is an anonymous type, then I dunno, but if you're just getting a named column with a primitive type, then this should work.

Crispy answered 17/5, 2009 at 15:3 Comment(0)
P
0

Hope this helps, am passing in an interface list, which I need to get a distinct list from. First I get an Anonymous type list, and then I walk it to transfer it to my object list.

private List<StockSymbolResult> GetDistinctSymbolList( List<ICommonFields> l )
            {
                var DistinctList = (
                        from a
                        in l
                        orderby a.Symbol
                        select new
                        {
                            a.Symbol,
                            a.StockID
                        } ).Distinct();

                StockSymbolResult ssr;
                List<StockSymbolResult> rl = new List<StockSymbolResult>();
                foreach ( var i in DistinctList )
                {
                                // Symbol is a string and StockID is an int.
                    ssr = new StockSymbolResult( i.Symbol, i.StockID );
                    rl.Add( ssr );
                }

                return rl;
            }
Preliminary answered 11/10, 2010 at 23:5 Comment(0)
J
0

You can loop through the properties of an anonymous type like this:

var obj = new {someValue = "hello", otherValue = "world"};
foreach (var propertyInfo in obj.GetType().GetProperties() {
    var name = propertyInfo.Name;
    var value = propertyInfo.GetValue(obj, index: null);
    ...
}
Jamestown answered 24/3, 2011 at 14:55 Comment(0)
A
0

If you know what you are doing and are not afraid of getting runtime errors when your code changes, you could cast your row data as dynamic:

var data = view.GetRow(rowHandle) as dynamic;  

int clientId      = data.ClientID;
string clientName = data.ClientName;
int jobs          = data.Jobs

No Compile-time verification. But it should work nicely.

Albino answered 23/7, 2013 at 8:36 Comment(0)
V
0
var result = ((dynamic)DataGridView.Rows[rowNum].DataBoundItem).value;
Venation answered 30/12, 2015 at 21:45 Comment(1)
This is the simplest fomra to get the value of the attributes of a list ( DataGridView )Venation

© 2022 - 2024 — McMap. All rights reserved.