7

私はIQuerable<object> sourceオブジェクトを持っていて、そこからそのようなものを取得する必要があります(ただし、リフレクションを使用しています)。

source.Select(t => new SelectListItem { Name = t.Name, Value = t.Id })

どうすればそれを行うことができますか、またはその種の式ツリーを構築するための参照をどこで見つけることができますか?

ありがとう

4

2 に答える 2

12

名前空間 ( MSDN )Expressionを使用してを作成できますSystem.Linq.Expressions

あなたの場合、次のようになります。

var source = typeof( Source );
var target = typeof( SelectListItem );

var t = Expression.Parameter( source, "t" );

var sourceName = Expression.MakeMemberAccess( t, source.GetProperty( "Name" ) );
var sourceId = Expression.MakeMemberAccess( t, source.GetProperty( "Id" ) );

var assignName = Expression.Bind( target.GetProperty( "Name" ), sourceName );
var assignValue = Expression.Bind( target.GetProperty( "Value" ), sourceId );
var targetNew = Expression.New( target );
var init = Expression.MemberInit( targetNew, assignName, assignValue );

var lambda =
  ( Expression<Func<Source,SelectListItem>> ) Expression.Lambda( init, t );

次のように使用できます。

IQueryable<Source> list = ...

List<SelectListItem> items = list.Select( lambda ).ToList();
于 2013-01-11T10:20:37.217 に答える
0

実行時にどの Type 情報 (存在する場合) が認識されるかについては、少し不明確です。Nicholas Butler の回答に便乗する(それが受け入れられているため) ソース タイプ (つまり、IQueryable ソースの T のタイプ) を「知っている」と仮定し、ターゲット タイプ (から返されたアイテム タイプ) を「知っている」と仮定しましょうIQueryable.Select 拡張メソッド)。私が「知っている」と言うとき、ダイナミクス、リフレクション、遅延バインディングなどなしで実行時に発見できるものであることを意味します。 (つまり、「名前/ID」と「名前/値」)。

これを考えると、ラムダ式を手動で構築する必要のない非常に簡単な解決策があります...

解決策: 最初に、これら 2 つのタイプを定義して、何を扱っているかを理解しましょう。これを行うのは、あなたが使用しているタイプがわからないためです。これらは実際に使用しているもののプレースホルダーであるため、デモ/例の目的のためだけに、ソリューションには必要ありません:

//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; }
}

次に、2 つのメソッドを持つ単純な静的クラスを定義します。1 つのメソッドはラムダ式を作成し、もう 1 つのメソッドはソース (IQueryable) を 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 };
    }
}

使用法:

    //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}";

では、どうぞ。それがあなたが探しているものかどうか、それともあなたのニーズに合っているかどうかはわかりません。うまくいけば、誰かがそれを役に立つと思うでしょう。

于 2015-10-31T00:16:32.833 に答える