I have a LINQ statement that returns an anonymous type. I need to get this type to be an ObservableCollection in my Silverlight application. However, the closest I can get it to a
List myObjects;
Can someone tell me how to do this?
ObservableCollection<MyTasks> visibleTasks = e.Result;
var filteredResults = from visibleTask in visibleTasks
select visibleTask;
filteredResults = filteredResults.Where(p => p.DueDate == DateTime.Today);
visibleTasks = filteredResults.ToList(); // This throws a compile time error
How can I go from a anonymous type to an observable collection?
Thank you
As Ekin suggests, you can write a generic method that turns any IEnumerable<T> into an ObservableCollection<T>. This has one significant advantage over creating a new instance of ObservableCollection using constructor - the C# compiler is able to infer the generic type parameter automatically when calling a method, so you don't need to write the type of the elements. This allows you to create a collection of anonymous types, which wouldn't be otherwise possible (e.g. when using a constructor).
One improvement over Ekin's version is to write the method as an extension method. Following the usual naming pattern (such as ToList or ToArray), we can call it ToObservableCollection:
static ObservableCollection<T> ToObservableCollection<T>
(this IEnumerable<T> en) {
return new ObservableCollection<T>(en);
}
Now you can create an observable collection containing anonymous types returned from a LINQ query like this:
var oc =
(from t in visibleTasks
where t.IsSomething == true
select new { Name = t.TaskName, Whatever = t.Foo }
).ToObservableCollection();
Something like this would do the job using type inference features:
private static ObservableCollection<T> CreateObservable<T>(IEnumerable<T> enumerable)
{
return new ObservableCollection<T>(enumerable);
}
static void Main(string[] args)
{
var oc = CreateObservable(args.Where(s => s.Length == 5));
}
You should just be able to do this:
visibleTasks = new ObservableCollection<MyTasks>(filteredResults);
Are you sure that your object is an ObservableCollection indeed? If yes, you can just cast: visibleTasks = (ObservableCollection)filteredResults;
Try:
var filteredResults = from visibleTask in visibleTasks
where(p => p.DueDate == DateTime.Today)
select visibleTask).ToList();
(filteredResults will contain your desired list)
Related
My code receives an anonymous object created by another method. I would like to access and iterate through the nested collection in this object. I was trying to come up with several different ways to cast it using the 'as' keyword but no avail.
Here is the code which creates the object:
var result = new object();
foreach (var item in items)
{
result = new
{
Variants = item.Value.Select(m => m.Item2).GroupBy(n => n.Item1).Select(r => new
{
Name = r.Key,
Items = r.Select(p => new
{
Value = p.Item2.Trim(),
Text = p.Item2.Substring(0, p.Item2.LastIndexOf('_')).Trim()
}).Where(p => !string.IsNullOrEmpty(p.Text)).ToList()
})
};
}
Visual Studio gives me the following signature when I hover over the variable which received this anonymous type:
{ Variants = {System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Linq.IGrouping<string, System.Tuple<string, string>>, <>f__AnonymousType1<string, System.Collections.Generic.List<<>f__AnonymousType2<string, string>>>>} }
In short: I would like to access the Text fields of the collection.
Here is the QuickWatch window showing the structure and data of this object:
QuickWatch Window
Would appreciate any help!
PS: Cannot change the code in the sending method.
If you don't have a static type of a class you can't cast to it. For anonymous types having its type means you either have it locally in the method or get as parameter of a generic method - neither is the case here.
You options are really limited to some sort of reflection to dig into anonymous class. The easiest way would be to let runtime deal with reflection by relying on dynamic like ((dynamic)myVariable).Text.
I want to convert following to list. I have fetched property using reflection, but how to convert them to list (in my case this is entity object DBSet).
and I need the result as list.
ClassObject.GetType().GetProperty(classname) //After getting property I need it in .ToList()
You can convert with a function like this.
If the reflected object is not enumerable, it can't be converted.
public static List<T> ConvertMysteriousObjectToList<T>(object input)
{
var enumerable = input as IEnumerable;
if (enumerable == null) throw new InvalidOperationException("The object is not convertible to a list.");
return enumerable.Cast<T>().ToList();
}
If you're trying to convert some flavor of DbSet (e.g. a DbSet<Foo>) then you'd call it like this:
var o = ClassObject.GetType().GetProperty(classname);
var list = ConvertMysteriousObjectToList<Foo>(o);
If you don't know the type:
var list = ConvertMysteriousObjectToList<object>(o);
or
var list = ConvertMysteriousObjectToList<dynamic>(o);
I got what I wanted.
static IEnumerable GetAllMembers(DbContext db, string dbSetName)
{
var pi = db.GetType().GetProperty(dbSetName);
return (IEnumerable)pi.GetValue(db);
}
source:
How to get DbSet<SomeClass> (EF) from the dbContext using reflection?
In C#, I have a class MyObj that implements an interface IMyInterface.
I now have a collection of lists of MyObj class:
IEnumerable<List<MyObj>> myObjGroups
and I want to convert / cast it to
IEnumerable<List<IMyInterface>> myInterfaceGroups
and everything I have tried has thrown an exception.
An exception of type 'System.InvalidCastException' occurred in System.Core.dll but was not handled in user code
Additional information: Unable to cast object of type 'System.Collections.Generic.List`1[MyObj]' to type 'System.Collections.Generic.List`1[IMyInterface]'.
I have tried:
IEnumerable<List<IMyInterface>> myInterfaceGroups= new List<List<IMyInterface>>(myObjGroups.Cast<List<IMyInterface>>());
and:
IEnumerable<List<IMyInterface>> myList = myObjGroups.Cast<List<IMyInterface>>();
and both seems to throw exceptions at run time.
Any suggestions on what i am doing wrong?
Try it the following way:
IEnumerable<List<IMyInterface>> myInterfaceGroups = myObjGroups
.Select(l => l.Select(o => (IMyInterface)o).ToList());
Or if you prefer using the Cast<T>() extension method:
IEnumerable<List<IMyInterface>> myInterfaceGroups = myObjGroups
.Select(l => l.Cast<IMyInterface>().ToList());
EDIT: A bit of explanation
To better understand why did you get the InvalidCastException exception, let's try to decompose your original expression:
IEnumerable<List<IMyInterface>> myInterfaceGroups =
new List<List<IMyInterface>>(myObjGroups.Cast<List<IMyInterface>>());
This is equivalent to:
IEnumerable<List<IMyInterface>> myObjGroupsAsInterfaceList = myObjGroups
.Cast<List<IMyInterface>>()
.ToList();
IEnumerable<List<IMyInterface>> myInterfaceGroups = new List<List<IMyInterface>>(myObjGroupsAsInterfaceList);
The Cast<T>() extension method just iterates through the items and tries to cast each item to type T. We could replace the functionality of Cast<T>() extension method combined with ToList<T>() with the following snippet:
List<List<IMyInterface>> myObjGroupsAsInterfaceList = new List<List<IMyInterface>>();
foreach (List<MyObj> myObjGroup in myObjGroups)
{
List<IMyInterface> myObjGroupAsInterface = myObjGroup; // Compile error!
myObjGroupsAsInterfaceList.Add(myObjGroupAsInterface);
}
So the root problem is that you cannot assign a List<MyObj> object to a variable of type List<IMyInterface>.
To find more explanation on why the above is not possible, take a look on the following question: C# variance problem: Assigning List<Derived> as List<Base>
You're doing something wrong. You can't cast an IEnumerable to a List. A list is an actual metrialized collection of data, while an run-time IEnumerable needs to be iterated over in order to retrieve the data.
To solve your problem, you need to Cast to IEnumerable<IMyInterface>:
Check a working Fiddle: Here (Same below)
public class Program
{
static IEnumerable<List<MyObj>> Get()
{
yield return new List<MyObj>();
yield return new List<MyObj>();
}
static void Main()
{
IEnumerable<List<MyObj>> myObjGroups = Get();
var result = myObjGroups.Cast<IEnumerable<IMyInterface>>();
foreach(var val in result)
Console.WriteLine(val.Count());
}
}
I have a List<> of abstract objects that contains different types of objects.
I am trying to grab all the items of a certain type and set those items to their own List<>.
This is not working -
//myAbstractItems is a List<myAbstractItem>
//typeAList inherents from myAbstractItem
var typeAList = ((List<itemTypeA>)myAbstractItems.Where(i => i.GetType() == typeof(itemTypeA)).ToList());
The casting (List<itemTypeA>) appears to be failing.
Use the OfType extension method:
var typeAList = myAbstractItems.OfType<itemTypeA>().ToList();
From the documentation...
The OfType(IEnumerable) method returns only those elements in source that can be cast to type TResult.
A good old loop should be fine :
List<itemTypeA> res = new List<itemTypeA>();
foreach(var item in myAbstractItems)
{
itemTypeA temp = item as itemTypeA;
if (temp != null)
res.Add(temp)
}
Try using Where this way:
var typeAList = myAbstractItems.Where(i => i.GetType() == typeof(itemTypeA)).Select(item => item as itemTypeA).ToList())
Another way you could do this is using the OfType() method:
var typeAList = myAbstractItems.OfType<itemTypeA>().ToList();
This method basically performs the following operation:
var typeAList = myAbstractItems.Where(i=>i is itemTypeA).Select(i=>i as itemTypeA).ToList();
Keep in mind that this will fail if any element of the source collection is a null reference.
This will work for all itemTypeAs (and more derived types).
var typeAList = myAbstractItems.Select(i => i as itemTypeA).Where(i => i != null).ToList();
EDIT: edited as per Rawling's comment.
I have an array of unknown (to the current method) class objects. I do know that each class has a property called "Number".
I am trying to write a LINQ query where I am looking for the object with the next Number in sequence. AKA, I'm at Number 8, use a LINQ query to find the object where Number=9.
Anyone got a suggestion?
Also, I use reflection often so don't worry about avoiding it.
You can create an interface - INumber with a property Number. Each of the objects that you are having in the array can implemen this interface.
That way, you will have an array of known type INumber. This way your query will be easy to debug and maintain.
If the objects all inherit from a known interface then you can cast them, e.g.
var next = items.Cast<IHasNumber>.FirstOrDefault(x => x.Number == index + 1);
If they don't, then you can use dynamic, e.g.
var next = items.Cast<dynamic>.FirstOrDefault(x => x.Number == index + 1);
If you have control of the types, then I would make them implement an interface so that you can use the first method, which should be significantly faster than the second. In that case, your collection will probably be IEnumerable<IHasNumber> to start with and you won't even have to cast.
If as you indicated elsewhere that you designed all the classes then you could put that number property in an in interface and have all the classes implement that interface. Then, in the linq query, use the interface.
If you truly do not have a common type that you can reduce to and for some reason cannot introduce such a type, then you may be able to use the dynamic keyword. I don't have access to a compiler at the moment, but can your method accept a collection of dynamic objects and query them?
For example:
IEnumerable<dynamic> collection = ...;
var numbers = from x in collection
select x.Number;
To avoid performance issues you can use the following method:
static void Main(string[] args)
{
object[] objs = GetInitialData();
var accessor = GetGetterHelper<int>(objs[0].GetType(), "Number");
var res = from a in objs where accessor(a) == 7 select a;
}
static Func<object, T> GetGetterHelper<T>(Type type, string methodName)
{
var methodInfo = type.GetProperty(methodName).GetGetMethod();
return x => (T)methodInfo.Invoke(x, new object[] {});
}