I'm using EntityFramework to a list of objects from the database and I'm using Anonymous Types to eventually return the right object. Because there are several functions that has to do this 'Anonymous type conversion' I want to extract this to functions.
I can create a function to create a dynamic but can't create a function that converts a dynamic in a specific type because if the function has a parameter that contains a dynamic, the return type is a dynamic type too.
This works:
List<SomeObject> list = list
.Select(i => GetAnonymousType(i))
.Select(i => new SomeObject {Item1 = i.Item1, Item2 =i.Item2}).ToList();
This doesn't:
List<SomeObject> list = list
.Select(i => GetAnonymousType(i))
.Select(i => CreateSomeObjectFromDynamic(i)).ToList();
private static SomeObject CreateSomeObjectFromDynamic(dynamic i)
{
return new SomeObject {Item1 = i.Item1, Item2 = i.Item2};
}
See: https://dotnetfiddle.net/zLFlur
Is there a way I can use a function like: CreateSomeObjectFromDynamic to return the right type?
try this:
list = list
.Select(i => GetAnonymousType(i))
.Select(i => CreateSomeObjectFromDynamic(i) as SomeObject).ToList();
According to provided code at fiddle, your problem is not with CreateSomeObjectFromDynamic method, your problem is with GetAnonymousType method. This method returns dynamic and .NET cannot handle it. The compliler error says that:
Cannot implicitly convert type
'System.Collections.Generic.List<dynamic>' to
'System.Collections.Generic.List<SomeObject>'
Even changing query to
list = list
.Select(i => CreateSomeObjectFromDynamic(GetAnonymousType(i)))
.ToList();
will produce the same error. But, if you change return type of GetAnonymousType method to object as below:
private static object GetAnonymousType(SomeObject i)
{
return new { Item1 = i.Item1, Item2 = i.Item2 };
}
your problem will be solved. But, this works in memory, I am not sure that it will successfully be translated into SQL if you try to use it with IQueryable for example. Also, I do not recomend using dynamic, even though it works after chaning return type to object your code does not seem right. If you make a bit effort, I am sure that you will find another way, for example using inheritance, generics and etc.
Related
Is there a Linq equivalent for the following piece of code where Properties is a list of properties in the object T and entry is an instance of T.
I find that I do code like this ever so often and I Was wondering if there was a more simple clear way to do this using linq.
List<Object> args = new List<Object>();
for (int i = 0; i < Properties.Count; i++)
args.Add(typeof(T).GetProperty(Properties[i]).GetValue(entry));
Properties.Select(t => typeof(T).GetProperty(t).GetValue(entry)).ToList();
now if you use often, just create an extension method (in a static helper class)
public static IList<object> GetValuesFor<T>(this IEnumerable<string> properties, T instance) {
return properties.Select(t => typeof(T).GetProperty(t).GetValue(instance)).ToList();
}
and usage
var args = Properties.GetValuesFor(entry);
You are transforming properties into values, which means that you can use the Select method:
var args = Properies.Select( p => typeof(T).GetProperty(p).GetValue(entry) );
var args = Properties
.Select(x=> typeof(T).GetProperty(x).GetValue(entry))
.ToList();
This should be the equivalent, using the Select method:
var args = Properties
.Select(p => typeof(T).GetProperty(p))
.Select(p => p.GetValue(entry))
.ToList();
You can of course have the whole typeof(T).GetProperty(p).GetValue(entry) part in one Select - I've split it for clarity. Note that it doesn't make much difference in terms of memory/performance - it won't create any additional collection in between, because LINQ is lazily evaluated, and it won't "run" until the ToList call.
I'm trying to build a SelectList from an Enum.
Why are the Linq extension methods not available on Array?
var values = Enum.GetValues(typeof(MyEnum));
var test = values.Select(x => x); // compile error
But I can write it this way and it compiles...
var test = from Enum e in values select new { e };
I don't normally use this style of syntax so I'm not really familiar with it, but isn't the above essentially the same as the lambda query which doesn't compile?
Use OfType method to get an IEnumerable<T> that can be queried using LINQ:
var values = Enum.GetValues(typeof(MyEnum));
var test = values.OfType<int>().Select(x => x);
I have a class Literal and a Tag is inheriting from it.
I would like to do the following but I am getting
Unable to cast object of type 'WhereListIterator`1[Core.Literal]' to type 'System.Collections.Generic.List`1[Core.Tag]'.
private List<Literal> literals;
public List<Tag> Tags
{
get { return (List<Tag>)literals.Where(x => x is Tag); }
}
thanks
You would be better off doing:
literals.OfType<Tag>().ToList();
This gives you a List<Tag>.
You can also do:
var asList = new List<Tag>(literals.OfType<Tag>());
Casting simply does not work because LINQ works in terms of either IEnumerable<T> or IQueryable<T> which neither use List as a backing implementation for the results. The second method I posted uses a constructor overload of List<T> the takes in an IEnumerable<T> as its initial collection of objects. Also in this scenario the OfType<T> method from LINQ is a much cleaner, shorter form of essentially filtering a list with Where(x -> x is T).
Also, OfType<T> in this scenario is a much better idea, because the result is an IEnumerable<T> of your target type. Where(x => x is T) will return an IEnumerable<T> of the original source's type. So that's why (List<Tag>)literals.Where(x => x is Tag).ToList() emit an error for invalid casts.
More information on ToList
More information on OfType
literals.Select(x => x as Tag).Where(x => x != null).ToList()
Note that this will return new list. You won't be able to do where and modify original list by this. Also this can be done like this: literals.OfType<Tag>().ToList() and it will return IList<Tag>
Update: modified type
List<Tag>)literals.Where(x => x is Tag).ToList();
or even better :
literals.OfType<Tag>();
then you can create a new list from it:
new List<Tag>(literals.OfType<Tag>());
Depending on the effect you want you could do this:
public List<Tag> Tags
{
get { return literals.Where(x => x is Tag).ToList(); }
}
Do realize that this is not a cast but the creation of a list!
How about adding ToList()?
Your getter becomes: literals.Where(x => x is Tag).ToList();
try the following:
literals.Where(x => x is Tag).Cast<Tag>().ToList();
it works if Tag is derived from Literal
The Where method returns the same type as the source, so you would have to cast each item, then use the ToList method to create a list from the result:
return literals.Where(x => x is Tag).Select(x => (Tag)x).ToList();
You can also us the OfType method:
return literals.OfType<Tag>().ToList();
What is the exact use of AsEnumerable? Will it change non-enumerable collection to enumerable
collection?.Please give me a simple example.
From the "Remarks" section of the MSDN documentation:
The AsEnumerable<TSource> method has no effect
other than to change the compile-time
type of source from a type that
implements IEnumerable<T> to
IEnumerable<T> itself.
AsEnumerable<TSource> can be used to choose
between query implementations when a
sequence implements IEnumerable<T> but also has a different set
of public query methods available. For
example, given a generic class Table
that implements IEnumerable<T> and has its own methods such
as Where, Select, and SelectMany, a
call to Where would invoke the public
Where method of Table. A Table type
that represents a database table could
have a Where method that takes the
predicate argument as an expression
tree and converts the tree to SQL for
remote execution. If remote execution
is not desired, for example because
the predicate invokes a local method,
the AsEnumerable<TSource>
method can be used to hide the custom
methods and instead make the standard
query operators available.
If you take a look in reflector:
public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
It basically does nothing more than down casting something that implements IEnumerable.
Nobody has mentioned this for some reason, but observe that something.AsEnumerable() is equivalent to (IEnumerable<TSomething>) something. The difference is that the cast requires the type of the elements to be specified explicitly, which is, of course, inconvenient. For me, that's the main reason to use AsEnumerable() instead of the cast.
AsEnumerable() converts an array (or list, or collection) into an IEnumerable<T> of the collection.
See http://msdn.microsoft.com/en-us/library/bb335435.aspx for more information.
From the above article:
The AsEnumerable<TSource>(IEnumerable<TSource>) method has no
effect other than to change the compile-time type of source from a type
that implements IEnumerable<T> to IEnumerable<T> itself.
After reading the answers, i guess you are still missing a practical example.
I use this to enable me to use linq on a datatable
var mySelect = from table in myDataSet.Tables[0].AsEnumerable()
where table["myColumn"].ToString() == "Some text"
select table;
AsEnumerable can only be used on enumerable collections. It just changes the type of the collection to IEnumerable<T> to access more easily the IEnumerable extensions.
No it doesn't change a non-enumerable collection to an enumerable one. What is does it return the collection back to you as an IEnumerable so that you can use it as an enumerable. That way you can use the object in conjunction with IEnumerable extensions and be treated as such.
Here's example code which may illustrate LukeH's correct explanation.
IEnumerable<Order> orderQuery = dataContext.Orders
.Where(o => o.Customer.Name == "Bob")
.AsEnumerable()
.Where(o => MyFancyFilterMethod(o, MyFancyObject));
The first Where is Queryable.Where, which is translated into sql and run in the database (o.Customer is not loaded into memory).
The second Where is Enumerable.Where, which calls an in-memory method with an instance of something I don't want to send into the database.
Without the AsEnumerable method, I'd have to write it like this:
IEnumerable<Order> orderQuery =
((IEnumerable<Order>)
(dataContext.Orders.Where(o => o.Customer.Name == "Bob")))
.Where(o => MyFancyFilterMethod(o, MyFancyObject));
Or
IEnumerable<Order> orderQuery =
Enumerable.Where(
dataContext.Orders.Where(o => o.Customer.Name == "Bob"),
(o => MyFancyFilterMethod(o, MyFancyObject));
Neither of which flow well at all.
static void Main()
{
/*
"AsEnumerable" purpose is to cast an IQueryable<T> sequence to IEnumerable<T>,
forcing the remainder of the query to execute locally instead of on database as below example so it can hurt performance. (bind Enumerable operators instead of Queryable).
In below example we have cars table in SQL Server and are going to filter red cars and filter equipment with some regex:
*/
Regex wordCounter = new Regex(#"\w");
var query = dataContext.Cars.Where(car=> article.Color == "red" && wordCounter.Matches(car.Equipment).Count < 10);
/*
SQL Server doesn’t support regular expressions therefore the LINQ-to-db providers will throw an exception: query cannot be translated to SQL.
TO solve this firstly we can get all cars with red color using a LINQ to SQL query,
and secondly filtering locally for Equipment of less than 10 words:
*/
Regex wordCounter = new Regex(#"\w");
IEnumerable<Car> sqlQuery = dataContext.Cars
.Where(car => car.Color == "red");
IEnumerable<Car> localQuery = sqlQuery
.Where(car => wordCounter.Matches(car.Equipment).Count < 10);
/*
Because sqlQuery is of type IEnumerable<Car>, the second query binds to the local query operators,
therefore that part of the filtering is run on the client.
With AsEnumerable, we can do the same in a single query:
*/
Regex wordCounter = new Regex(#"\w");
var query = dataContext.Cars
.Where(car => car.Color == "red")
.AsEnumerable()
.Where(car => wordCounter.Matches(car.Equipment).Count < 10);
/*
An alternative to calling AsEnumerable is ToArray or ToList.
*/
}
The Enumerable.AsEnumerable method can be used to hide a type's custom implementation of a standard query operator
Consider the following example. we have a custom List called MyList
public class MyList<T> : List<T>
{
public string Where()
{
return $"This is the first element {this[0]}";
}
}
MyList has a method called Where which is Enumerable.Where() exact same name. when I use it, actually I am calling my version of Where, not Enumerable's version
MyList<int> list = new MyList<int>();
list.Add(4);
list.Add(2);
list.Add(7);
string result = list.Where();
// the result is "This is the first element 4"
Now how can I find the elements which are less than 5 with the Enumerable's version of Where?
The answer is: Use AsEnumerable() method and then call Where
IEnumerable<int> result = list.AsEnumerable().Where(e => e < 5);
This time the result contains the list of elements that are less than 5
I am using WCF REST Preview 2 to test some REST services. The package has an extension to IEnumerable as ToDictionary(Func(TSource, TKey) keySelctor. Not sure how to define a lambda function to return keySelector?
Here is one example:
var items = from x in entity.Instances // a customized Entity class with list instances of MyClass
select new { x.Name, x};
Dictionary<string, MyClass> dic = items.ToDictionary<string, MyClass>(
(x, y) => ... // what should be here. I tried x.Name, x all not working
Not sure what should be the lambda Func should be to return a KeySelector?
Since items is of type IEnumerable<MyClass>, you should be able to do the following:
items.ToDictionary(x => x.Name)
You could even have done:
entity.Instances.ToDictionary(x => x.Name)
You don't need to specify the type parameters, since they can be correctly inferred.
Edit:
items.ToDictionary(x => x.Name) is actually incorrect, because items is not of type IEnumerable<MyClass>. It is actually an IEnumerable of the anonymouse type, that has 2 properties (Name, which contains the myClass.Name property, and x, which is of type MyClass).
In that case, assuming you can do:
var items = from instance in entity.Instances
select new { Name = instance.Name, // don't have to specify name as the parameter
Instance = instance
};
var dict = items.ToDictionary(item => item.Name,
item => item.Instance);
The second example is a bit easier to use in this case. Essentially, you don't get any value from the linq query to get items, if all you're trying to do is generate a dictionary.