2

私はラムダに不慣れです。質問が単純な場合はすみません。

リフレクションを使用していくつかのタイプにプロパティを設定するメソッドがあります。

public void WriteId(object obj, int id) {
    var type = obj.GetType();
    var prop = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                   .Where(p => p.CanRead && p.CanWrite)
                   .Where(p => p.Name == "Id")
                   .Where(p.PropertyType == typeof(int))
                   .FirstOrDefault();
    if(prop != null)
        prop.SetValue(obj, id, null);
}

同じ仕事をするラムダを作成するにはどうすればよいですか?実際、タイプごとにラムダを作成し、コンパイルしてキャッシュしたいと思います。前もって感謝します。

4

1 に答える 1

4

NuGetからFastMemberをインストールしてから、次を使用します。

var wrapped = ObjectAccessor.Create(obj);
obj["Id"] = id;

これは、 (ではなく)ILGeneratorを介して使用されることを除いて、あなたの言うこととほぼ同じですが、すべてのキャッシングなどがあります。TypeBuilderExpression

2つ目の生意気なアプローチは、dynamicすべてを自分で行うことです。

((dynamic)obj).Id = id;

Expressionただし、他の理由で使用する場合:

using System;
using System.Linq.Expressions;   

static class Program
{
    static void Main()
    {
        var obj = new Foo { Id = 2 };
        WriteId(obj, 6);
        Console.WriteLine(obj.Id); // 6
    }

    private static class SneakyCache<T>
    {
        public static readonly Action<T, int> SetId;
        static SneakyCache()
        {
            var obj = Expression.Parameter(typeof(T), "obj");
            var id = Expression.Parameter(typeof(int), "id");
            SetId = Expression.Lambda<Action<T, int>>(
                  Expression.Assign(Expression.Property(obj, "Id"), id),
                  obj, id).Compile();
        }
    }
    public static void WriteId<T>(T obj, int id) where T : class
    {
        SneakyCache<T>.SetId(obj, id);
    }
}
class Foo
{
    public int Id { get; set; }
}
于 2012-09-28T05:15:56.503 に答える