Using Linq Zip function to merge collections for a view in Silverlight
Based upon a prior question I had Here. I wanted to join two collections together so that the merged data could be then displayed within a DataGrid of a Silverlight UI.
Using the Linq Zip function I was able to merge my two collections as follows
public void CombineAllCollections()
{
var combineAll = Persons.Zip(PhoneNumbers, (x, y) => new
{
FirstName = x.FirstName,
LastName = x.LastName,
Address = x.Address,
State = x.State,
Zip = x.Zip,
AreaCode = y.AreaCode,
PhoneNumber = y.Number
});
}
This seems to do just what I wanted. However the output is an Anonymous Type. How can I cast the combinedAll type to a collection (List, ObservableColl. IENum) that I can then pass to a view in my UI ( Bind to a datagrid) . Th开发者_如何学Pythone output should then display within the grid a column and value for each item ( as listed above seven columns).
Thanks in advance
-Cheers
Instead of making an anonymous type, you could create a concrete type specifically for the merged results with all of the properties you specified on the anonymous type.
For example:
public void CombineAllCollections()
{
var combineAll = Persons.Zip(PhoneNumbers, (x, y) => new PersonWithPhoneNumber
{
FirstName = x.FirstName,
LastName = x.LastName,
Address = x.Address,
State = x.State,
Zip = x.Zip,
AreaCode = y.AreaCode,
PhoneNumber = y.Number
});
}
Where PersonWithPhoneNumber
is the type with all of the specified properties.
Then you can call ToList() on the result to convert it to an IList<PersonWithPhoneNumber>
or you can leave it in the form it is in as an IEnumerable<PersonWithPhoneNumber>
EDIT
Given the information that you provided, it would appear about the only effective way to store so many values while maintaining the ability to use LINQ and not have to define a separate type would be to create a dictionary for each item in the zipped collection, for example:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var xs = new[] {1, 2, 3, 4, 5, 6};
var ys = new[] {7, 8, 9, 10, 11, 12};
var zipped = xs.Zip(ys, (x, y) =>
new Dictionary<string, object>
{
{ "X", x},
{ "Y", y}
});
foreach (var pair in zipped.SelectMany(tuple => tuple))
{
Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
}
}
}
}
This way, you can have as many Key/Value pairs in the dictionary for each item as you would like. However, you essentially lose any type safety using this method and will end up boxing all value types for each property. This means you will have to know the type to cast back to. I would honestly not recommend doing this. I would simply just make a type, even if that type needs 100 properties. In this scenario auto-properties and a good text editor are your best friend.
You could also us the new dynamic type in C# 4 with the .NET 4.0 framework as in the following example:
using System;
using System.Dynamic;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var xs = new[] {1, 2, 3, 4, 5, 6};
var ys = new[] {7, 8, 9, 10, 11, 12};
var zipped = xs.Zip(ys, (x, y) =>
{
dynamic value = new ExpandoObject();
value.X = x;
value.Y = y;
return value;
});
foreach (var pair in zipped)
{
Console.WriteLine("X = {0}, Y = {1}", pair.X, pair.Y);
}
}
}
}
This will introduce dynamic into your code, though. Which may not have the performance metrics you desire and can lead to a lot of run-time errors if you don't keep an eye out on what you're doing. This is because you could misspell a property while creating or accessing it (this is also an issue with the dictionary setup) which will lead to a run-time exception when you attempt to access it. Again, probably best to just use a concrete, named typed in the end.
精彩评论