C# 将反射方法转换为编译的lambda

C# 将反射方法转换为编译的lambda,c#,reflection,lambda,C#,Reflection,Lambda,我是兰姆达的新手。如果我的问题很简单,请原谅 我有一个方法,它使用反射在某些类型上设置属性: public void WriteId(object obj, int id) { var type = obj.GetType(); var prop = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.CanRead &&am

我是兰姆达的新手。如果我的问题很简单,请原谅

我有一个方法,它使用反射在某些类型上设置属性:

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);
}
你能告诉我,我如何才能创建一个lambda做同样的工作?实际上,我想为每种类型创建一个lambda,编译它,并缓存它。提前感谢。

我将从NuGet安装,然后使用:

var wrapped = ObjectAccessor.Create(obj);
obj["Id"] = id;
它和你说的差不多,除了它碰巧通过
TypeBuilder
(而不是
Expression
)使用
ILGenerator
),但是所有的缓存都在那里

第二种方法是让
dynamic
为您完成这一切:

((dynamic)obj).Id = id;
但如果出于其他原因要使用
表达式

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; }
}
使用系统;
使用System.Linq.Expressions;
静态类程序
{
静态void Main()
{
var obj=newfoo{Id=2};
WriteId(obj,6);
Console.WriteLine(obj.Id);//6
}
私有静态类
{
公共静态只读操作SetId;
静态缓存()
{
var obj=表达式参数(类型(T),“obj”);
var id=表达式参数(typeof(int),“id”);
SetId=Expression.Lambda(
Expression.Assign(Expression.Property(obj,“Id”),Id),
obj,id.Compile();
}
}
公共静态void WriteId(T obj,int id),其中T:class
{
SetId(obj,id);
}
}
福班
{
公共int Id{get;set;}
}
我将从NuGet安装,然后使用:

var wrapped = ObjectAccessor.Create(obj);
obj["Id"] = id;
它和你说的差不多,除了它碰巧通过
TypeBuilder
(而不是
Expression
)使用
ILGenerator
),但是所有的缓存都在那里

第二种方法是让
dynamic
为您完成这一切:

((dynamic)obj).Id = id;
但如果出于其他原因要使用
表达式

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; }
}
使用系统;
使用System.Linq.Expressions;
静态类程序
{
静态void Main()
{
var obj=newfoo{Id=2};
WriteId(obj,6);
Console.WriteLine(obj.Id);//6
}
私有静态类
{
公共静态只读操作SetId;
静态缓存()
{
var obj=表达式参数(类型(T),“obj”);
var id=表达式参数(typeof(int),“id”);
SetId=Expression.Lambda(
Expression.Assign(Expression.Property(obj,“Id”),Id),
obj,id.Compile();
}
}
公共静态void WriteId(T obj,int id),其中T:class
{
SetId(obj,id);
}
}
福班
{
公共int Id{get;set;}
}

完全重复:@Dennis感谢link。我看到了,但对我来说理解起来更复杂。完全相同:@Dennis感谢link。“我看到了,但对我来说理解起来更复杂了。”马克·格雷威尔感谢他快速的回答。我不想使用准备好的代码。我想学习。你能给我看一下lambda(或ilgenerator)代码吗?@king.net添加了lambda方法;如果你想的话,我可以添加ILGenerator。在上面使用泛型是非常方便地进行缓存的一种简便方法,但是如果您只有
对象
,我们可以解决这个问题it@MarkGravell我现在知道你是FastMember的所有者。非常感谢。干得好,干得好。请问我在哪里可以找到FastMember的学习资源?我可以吗?@king.net您可能只需要使用一行程序,不过-
动态
在一些方面非常方便:
((动态)obj).Id=Id@markgravel但是如果obj没有Id属性会发生什么呢?@markgravel感谢您快速的回答。我不想使用准备好的代码。我想学习。你能给我看一下lambda(或ilgenerator)代码吗?@king.net添加了lambda方法;如果你想的话,我可以添加ILGenerator。在上面使用泛型是非常方便地进行缓存的一种简便方法,但是如果您只有
对象
,我们可以解决这个问题it@MarkGravell我现在知道你是FastMember的所有者。非常感谢。干得好,干得好。请问我在哪里可以找到FastMember的学习资源?我可以吗?@king.net您可能只需要使用一行程序,不过-
动态
在一些方面非常方便:
((动态)obj).Id=Id@markgravel但如果obj没有Id属性会发生什么?