Jest trochę niejasne, jakie informacje o typie (jeśli są) są znane podczas uruchamiania. Piggybacking na Odpowiedź Nichola Butlera na (ponieważ została przyjęta) Załóżmy, że "znasz" typ źródła (tj. Jaki jest typ T w źródle IQueryable) i "znasz" typ celu (typ pozycji zwrócono z metody rozszerzenia IQueryable.Select). Kiedy mówię "wiem", mam na myśli, że jest to coś, co można odkryć w czasie wykonywania bez dynamiki, refleksji, późnego wiązania itp. W przeciwnym razie jego rozwiązanie będzie działać tylko wtedy, gdy typy źródłowe i docelowe będą miały właściwości z pasującymi nazwami. ("Nazwa/Id" & "Nazwa/Wartość").
Biorąc pod uwagę to, że jest to całkiem proste rozwiązanie bez konieczności ręcznego skonstruować swój wyrażenia lambda ...
Rozwiązanie: Pierwszy pozwala zdefiniować te 2 typy tak wiemy, co mamy do czynienia. I tylko to zrobić, ponieważ nie wiem, jakiego rodzaju używasz, więc są naprawdę zastępcze do czego faktycznie użyciu, więc to nie jest potrzebne do rozwiązania, tylko na demo/przykładowych celów:
//this is whatever your source item type is (t)
public class NameIdPair
{
public string Name { get; set; }
public string Id { get; set; }
}
//this is whatever the SelectListItem type is you're using
public class SelectListItem
{
public string Name { get; set; }
public string Value { get; set; }
}
Następnie definiujemy prostą klasę statyczną za pomocą 2 metod. Jedną z metod stworzy wyrażenia lambda, a druga metoda będzie konwertować i wybierz źródło (IQueryable) do IEnumerable:
public static class QueryableExtensions
{
public static IEnumerable<TItem> Select<TSource, TItem>(this IQueryable<TSource> source)
where TSource : NameIdPair
where TItem : SelectListItem, new()
{
if (source == null) throw new ArgumentNullException("source");
return source.Select(CreateLambda<TSource, TItem>());
}
public static Expression<Func<TSource, TItem>> CreateLambda<TSource, TItem>()
where TSource : NameIdPair
where TItem : SelectListItem, new()
{
return (t) => new TItem { Name = t.Name, Value = t.Id };
}
}
Zastosowanie:
//create an instance of an IQueryable<T> for demo purposes
var source = new[]
{
new NameIdPair {Name = "test1_name", Id = "test1_Id"},
new NameIdPair {Name = "test2_name", Id = "test2_Id"}
}.AsQueryable();
//you can call the "Select" extension method to select the queryable into an enum.
var enumerable = source.Select<NameIdPair, SelectListItem>();
//'enumerable' is an IEnumerable<SelectListItem> instance
//or if you just want the lambda expression...
var lambda = QueryableExtensions.CreateLambda<NameIdPair, SelectListItem>();
//lambda.ToString() returns "t => new SelectListItem() {Name = t.Name, Value = t.Id}";
Więc pójdziesz. Nie wiem, czy to jest to, czego szukasz, lub jeśli odpowiada Twoim potrzebom. Miejmy nadzieję, że ktoś okaże się przydatny.
jeśli znasz typ, którego możesz używać Enumerable.Cast: http://msdn.microsoft.com/en-us/library/bb341406.aspx –
Czy byłaby to opcja rzutowania elementów na 'dynamic'? – Douglas
dynamiczne dźwięki to lepsza opcja niż odbicie. Wygląda dość niewygodnie, aby użyć refleksji. Wy nie możesz użyć czegoś, co jest zgodne z interfejsem takim jak INameValuePair? – mathk