views:

805

answers:

6

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.

+5  A: 

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.

JaredPar
"hacky anonymous type casts" what are those?
AnthonyWJones
@AnthonyWJones, I added an example of a hacky anonymous type cast
JaredPar
A: 

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.

Kevin
+1  A: 

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.

Sven Künzler
+1  A: 

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");
Hugoware
+1  A: 

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...
Bigabdoul
Thanks abdoul, your code is pretty easy to understand. I recently had a problem getting anonymous type and here:http://stackoverflow.com/questions/3534969/only-parameterless-constructors-and-initializers-are-supported-in-linq-to-entitieI left the question. After some searching and working on the weekend I came to this page and it really made my day.
fzshah76
A: 

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