9

同様:文字列をLinq.Expressionsに変換しますか、それとも文字列をセレクターとして使用しますか?

その類似したもの:Linq式を文字列として渡す?

同じ答えの別の質問:C#の文字列から動的ラムダベースのLinq式を作成するにはどうすればよいですか?

同様の質問がたくさんあるものを尋ねる理由:

これらの同様の質問で受け入れられた答えは、古いフレームワーク(.net 3.5)用に作成された4年前のライブラリ(コードマスターScott Guによって作成されたことを認める)をすべて参照し、答えとしてリンク。

ライブラリ全体を含めずにコードでこれを行う方法があります。

この状況のサンプルコードは次のとおりです。

    public static void getDynamic<T>(int startingId) where T : class
    {
        string classType = typeof(T).ToString();
        string classTypeId = classType + "Id";
        using (var repo = new Repository<T>())
        {
            Build<T>(
             repo.getList(),
             b => b.classTypeId //doesn't compile, this is the heart of the issue
               //How can a string be used in this fashion to access a property in b?
            )
        }
    }

    public void Build<T>(
        List<T> items, 
        Func<T, int> value) where T : class
    {
        var Values = new List<Item>();
        Values = items.Select(f => new Item()
        {
            Id = value(f)
        }).ToList();
    }

    public class Item
    {
     public int Id { get; set; }
    }

これは、文字列全体を次のような式に変換することを目的としていないことに注意してください。

query = "x => x.id == somevalue";

しかし、代わりにアクセスとして文字列のみを使用しようとしています

query = x => x.STRING;
4

3 に答える 3

15

これが式ツリーの試みです。これがEntityFrameworkで機能するかどうかはまだわかりませんが、試してみる価値はあると思います。

Func<T, int> MakeGetter<T>(string propertyName)
{
    ParameterExpression input = Expression.Parameter(typeof(T));

    var expr = Expression.Property(input, typeof(T).GetProperty(propertyName));

    return Expression.Lambda<Func<T, int>>(expr, input).Compile();  
}

このように呼んでください:

Build<T>(repo.getList(), MakeGetter<T>(classTypeId))

Expression<Func<T,int>>だけの代わりにinを使用できる場合はFunc、への呼び出しを削除しますCompile(そしての署名を変更しますMakeGetter)。


編集:コメントの中で、TravisJは次のようにそれをどのように使用できるかを尋ねました:w => "text" + w.classTypeId

これを行うにはいくつかの方法がありますが、読みやすくするために、最初に次のようにローカル変数を導入することをお勧めします。

var getId = MakeGetter<T>(classTypeId);

return w => "text" + getId(w); 

重要な点は、ゲッターは単なる関数であり、通常どおりに使用できるということです。このように読んでくださいFunc<T,int>int DoSomething(T instance)

于 2012-07-13T23:50:04.207 に答える
2

これが私のテストコード(linqPad)を使った拡張メソッドです:

class test
{
   public string sam { get; set; }
   public string notsam {get; set; }
}

void Main()
{
   var z = new test { sam = "sam", notsam = "alex" };

   z.Dump();

   z.GetPropertyByString("notsam").Dump();

   z.SetPropertyByString("sam","john");

   z.Dump();
}

static class Nice
{
  public static void  SetPropertyByString(this object x, string p,object value) 
  {
     x.GetType().GetProperty(p).SetValue(x,value,null);
  }

  public static object GetPropertyByString(this object x,string p)
  {
     return x.GetType().GetProperty(p).GetValue(x,null);
  }
}

結果:

結果

于 2012-07-14T00:14:49.330 に答える
1

私はこれを試していません、そしてそれがうまくいくかどうかはわかりませんが、あなたは次のようなものを使うことができますか?

b => b.GetType().GetProperty(classTypeId).GetValue(b, null);

于 2012-07-13T23:46:45.900 に答える