Using Linq extension on Array class - c#

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);

Related

Create Object from Anonymous Type

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.

c# How can I create a collection of custom objects without going through each field

I have created a class called DataResponse that has more than 40 public fields. The class DataResponse has the same number of fields and type as what's in my database DataRepoes (let's assume that).
Is there a way at all to do something like linq below where I create list of objects and automatically the fields are assigned to DataResponse from what's in the DB? Otherwise I have to spell out each and every those 40 fields and assign them manually when I new up DataResponse class. Thanks
List<Classes.DataResponse> res = (from rx in con.DataRepoes
where iaccess.Contains(rx.STOREID)
select new Classes.DataResponse).ToList<Classes.DataResponse>();
You can use Automapper Queryable Extensions for that.
Assuming the fields in Classes.DataResponse have the same names as the ones in DataRepoes you can then, do:
// During your application bootstrap, configure AutoMapper to create a map between the two types
Mapper.Initialize(cfg => cfg.CreateMap<DataRepoes, Classes.DataResponse);
// Then you can ask AutoMapper to project the IQueryable directly to your DTO
List<Classes.DataResponse> res = con.DataRepoes
.Where(rx => iaccess.Contains(rx.STOREID))
.ProjectTo<Classes.DataResponse>()
.ToList();
If you don't need the flexibility provided by AutoMapper or don't want using a third party library, you can use the following simplified custom extension method:
public static class QueryableExtensions
{
public static IQueryable<TResult> SelectTo<TResult>(this IQueryable source)
{
var sourceType = source.ElementType;
var resultType = typeof(TResult);
var parameter = Expression.Parameter(sourceType, "x");
var bindings =
from rm in resultType.GetProperties().Concat<MemberInfo>(resultType.GetFields())
join sm in sourceType.GetProperties().Concat<MemberInfo>(sourceType.GetFields())
on rm.Name equals sm.Name
select Expression.Bind(rm, Expression.MakeMemberAccess(parameter, sm));
var body = Expression.MemberInit(Expression.New(resultType), bindings);
return source.Provider.CreateQuery<TResult>(Expression.Call(
typeof(Queryable), "Select", new[] { sourceType, resultType },
source.Expression, Expression.Quote(Expression.Lambda(body, parameter))));
}
}
It will try to select all the properties/fields that match by name. Will fail if matched property/field types differ.
Sample usage:
Method syntax
var res = con.DataRepoes
.Where(rx => iaccess.Contains(rx.STOREID))
.SelectTo<Classes.DataResponse>()
.ToList();
Query syntax
var res =
(from rx in con.DataRepoes
where iaccess.Contains(rx.STOREID)
select rx)
.SelectTo<Classes.DataResponse>()
.ToList();
This is not possible using LINQ.
However you can use "AutoMapper" to acheive this.
Just CreateMap for these two class and then Map them
Mapper.CreateMap<DataResponse,DataRepo>();//Assuming DataRepoes is collection of DataRepo types
List<Classes.DataResponse> res = (from rx in con.DataRepoes
where iaccess.Contains(rx.STOREID)
select Mapper.Map<Classes.DataResponse>(rx)).
ToList<Classes.DataResponse>();
Hope that helps!!

Is there a Linq equivalent for creating collection from subset of an object used in a previous collection

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.

Create list IEnumerable<CustomClass> using a property of type CustomClass?

How can I intelligently create a List<int> from an IEnumerable<CustomClass>, if CustomClass has a property of type int, called customProperty which I wish to use to create my List<int> ?
I know I can create a List<CustomClass> by calling instance.ToList<CustomClass>();
How can I extract the property info to populate my list? What is best practice here ?
Using Linq, you can project to the property and ToList() the resulting IEnumerable<int>:
var ints = customClasses.Select(c => c.customProperty).ToList();
If you have never seen Linq extension methods before, Select is a common "projection" method. It takes a lambda expression, in this case an expression taking a type CustomClass represented as c, it returns whatever you want it to, in this case an int. As Select is working on a set (enumerable of something) you actually get an IEnumerable<int> in response, it can infer the type of IEnumerable based on your Select lambda.
If you want a delay-run IEnumerable<int>, simply drop the ToList() call.
I never like to impart opinion on best practice, but this is a clean one-liner that clearly shows intent (assuming basic understanding of Linq) and I see it all over the place.
Linq Resources:
http://www.codeproject.com/Articles/84521/LINQ-for-the-Beginner
http://www.codeproject.com/Articles/19154/Understanding-LINQ-C
Lambda Expression Resources:
http://msdn.microsoft.com/en-us/library/bb397687.aspx
Alternatively, these topics are very easily searched with terms like "LINQ tutorials" or "lambda expression tutorials".
Assuming C# 3.0, and hence LINQ,
var intList = instance.Select(cc => cc.customProperty).ToList();
This is easily done using a Linq projection. With functional notation:
var myEnumerable = new IEnurable<CustomClass>;
// ... fill myEnumerable
List<int> customProperties
= myEnumrable.Select(item => item.customProperty).ToList();
The lambada expression item => item.customProperty projects the int, so you get a list of int. Basically, the lambda expression is equivalent of a function which receives item as parameter and returns item.customProperty as result. Something like int foo(CustomaClass item) { return item.customProperty}. The particularity of the lambda expression is that it's anonymous (there is no foo) and the return and parameter types are inferred from the context.
Lambda Expressions (C# Programming Guide)
Alternative:
List<int> customProperties
= (from item in myEnumerable
select item.customProperty).ToList();
In this case the projection is done directly in the select clause. All the LINQ query is between paretheses to allow materializing it with ToList().
Query Expression Syntax Examples: Projection
And here I leave a code fragment where you can see all the variations of a similar query:
public class Thing
{
public string Name { get; set; }
public decimal Value { get; set; }
}
public decimal GetValue(Thing thing)
{
return thing.Value;
}
public Thing[] Things =
{
new Thing { Name="Stapler", Value=20.35M},
new Thing { Name="Eraser", Value=0.65M}
};
[TestMethod]
public void GetValueListFromThing()
{
// query notation, direct projection
List<decimal> valuesA
= (from t in Things
select t.Value).ToList();
// query notation, projection with method
List<decimal> valuesB
= (from t in Things
select GetValue(t)).ToList();
// functional notation, projection with method
List<decimal> valuesC
= Things.Select(t => GetValue(t)).ToList();
// functional notation, projection with anonymous delegate
List<decimal> valuesD
= Things.Select(t => { return t.Value; }).ToList();
// functional notation, lambda expression
List<decimal> values
= Things.Select(t => t.Value).ToList();
}

Nested lists, how I can do this with lambda expression?

Can't really understand how the select extension method works with a list inside another list, like this:
var queries = (from item in list
from item2 in list.anotherlist
select item2).ToList<MyType>();
This will not work:
// Gives me a list of List<QueryResult>
var queries = list.Select(item => item.anotherlist).ToList();
The SelectMany operator ought to do the trick - in this case, it takes a list of lists and flattens it:
var queries = list.SelectMany(sublist => sublist).ToList();
use selectmany
var queries = list.SelectMany(l => l.anotherList).ToList();

Categories