Cast list <object> to AnonymousTypes list

I populated the following list with objects like AnonymousType

 List<object> someList = new List<object>(); someList.Add(new { foo = 1 }); 

My problem is that I cannot get him to type strict code to do something like this:

 someList.Where(x=> x.foo == 1); 

However, this is possible on this list:

 var someList = new[] { new { foo = 1 } }; 

Can I make my first list so that it behaves like a second list? I want to be able to use lambda expressions for properties, as shown above.

+6
source share
2 answers

You can use generics and output type to create a list for you:

 public static List<T> CreateAnonymousList<T>(params T[] entries) { return new List<T>(entries); } 

Using:

 var someList = CreateAnonymousList(new { foo = 1 }, new { foo = 2 }, new { foo = 1 }); someList.Where(x => x.foo == 1); 

Naturally, you will not be able to cope much with this. You can never strictly enter it into your code for anything other than var , or return it from your method or something that you usually cannot do with anonymous types. If you want to do more, you just have to bite a (small) bullet and define a class for your anonymous type.


Rereading your question, you can still execute LINQ queries in an array:

 var someArray = new[]{new { foo = 1 }, new { foo = 2 }, new { foo = 1 }}; someArray.Where(x => x.foo == 1) 

So, if you do not modify it (say, using standard List<T> operations, such as Add or Remove ), then there is no reason to convert it to List<T> .

I understand that perhaps you can still pass it (for some reason) and still perform operations on it without knowing its anonymous type. In this case, you can consider it dynamic and perform operations at runtime, but you lose any intellisense / strong typing that you usually use with an anonymous type:

 List<dynamic> someDynamicList = new List<dynamic>() {new { foo = 1 }, new { foo = 2 }, new { foo = 1 }}; someDynamicList.Where(x => x.foo == 1) 

The last method, designated by Tim Schmelter , using Jon Skeet CastByExample, but extended to transform your collection using the extension method:

 public static IEnumerable<T> CastByExample<T>(this IEnumerable source, T example) { foreach(object entry in source) yield return (T)entry; } public static IEnumerable CreateAnonymousData() { return new[]{new { foo = 1 }, new { foo = 2 }, new { foo = 1 }}; } 

Using for example:

 var anonymousData = CreateAnonymousData(); var typedAnonymousData = anonymousData.CastByExample(new { foo = 1 }); typedAnonymousData.Where(x => x.foo == 1); 

This exploits the fact that in the same assembly, anonymous types declared with the same parameter names, types, and order are compiled into the same type. This will not work if you need to call your CreateAnonymousData from outside the current assembly, and you must support the signatures of your anonymous type foo wherever you use it (add / change its signature, you must update it everywhere use it or you will have a bad time) .

But I think it’s now becoming clearer that the best solution for this is to simply define a class representation of your anonymous type.

+9
source

You can use Jon Skeets CastByExample :

 public static T CastByExample<T>(object input, T example) { return (T)input; } List<object> someList = new List<object>() { new { foo = 1 },new { foo = 2 },new { foo = 3 } }; var example = new { foo = 0 }; foreach (object obj in someList) { var x = CastByExample(obj, example); Console.WriteLine("Foo: " + x.foo); } 
+4
source

Source: https://habr.com/ru/post/948783/


All Articles