使用C#表达式树,我可以创建一个匿名到类型化的对象映射吗?

使用C#表达式树,我可以创建一个匿名到类型化的对象映射吗?,c#,lambda,linq-expressions,C#,Lambda,Linq Expressions,这是在数据层上,因此性能非常重要。否则,我会使用Automapper。如果是IDB连接,我会用简洁的 我想将匿名对象的简单创作过程带到POCO中,并使用编译后的表达式来表达它 代码 public class Foo { public string Bar{get;set;} public string Baz{get;set;} } public void doStuff() { var obj = new{Bar= "My Name, Baz = "Some oth

这是在数据层上,因此性能非常重要。否则,我会使用Automapper。如果是IDB连接,我会用简洁的

我想将匿名对象的简单创作过程带到POCO中,并使用编译后的表达式来表达它

代码

public class Foo
{
    public string Bar{get;set;}
    public string Baz{get;set;}
}

public void doStuff()
{
     var obj = new{Bar= "My Name, Baz = "Some other data"};

     //can I recreate this assignment to foo using expressions?
     var foo = new Foo{
         Bar = obj.Bar,
         Baz = obj.Baz
     }
}
(不完整)到目前为止,我已经……

var props = o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)

    foreach (var prop in props)
                {
                    var targetProp = typeof(T).GetProperty(prop.Name);
                    var targetExp = Expression.Parameter(typeof(T), "target");
                    var valueExp = Expression.Parameter(prop.PropertyType, "property");



                    var propExp = Expression.Property(targetExp, targetProp);
                    var assignExp = Expression.Assign(propExp, valueExp);

                    var setter = Expression.Lambda<Action<T, object>>(assignExp, targetExp, valueExp).Compile();
                }
var props=o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
foreach(道具中的var道具)
{
var targetProp=typeof(T).GetProperty(prop.Name);
var targetExp=表达式参数(typeof(T),“target”);
var valueExp=Expression.Parameter(prop.PropertyType,“property”);
var propExp=Expression.Property(targetExp,targetProp);
var assignExp=Expression.Assign(propExp,valueExp);
var setter=Expression.Lambda(assignExp,targetExp,valueExp).Compile();
}
当前问题

  • 如何将setter组合成一个返回编译委托
  • 在属性上循环时,如何创建Lambda[Action]泛型类型
  • 感谢您的所有意见。

    给您:

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace Tests
    {
        public static class Utils
        {
            public static Func<TInput, TOutput> CreateMapFunc<TInput, TOutput>()
            {
                var source = Expression.Parameter(typeof(TInput), "source");
                var body = Expression.MemberInit(Expression.New(typeof(TOutput)),
                    source.Type.GetProperties().Select(p => Expression.Bind(typeof(TOutput).GetProperty(p.Name), Expression.Property(source, p))));
                var expr = Expression.Lambda<Func<TInput, TOutput>>(body, source);
                return expr.Compile();
            }
        }
        public static class MapFunc<TInput, TOutput>
        {
            public static readonly Func<TInput, TOutput> Instance = Utils.CreateMapFunc<TInput, TOutput>();
        }
        public struct Unit<T>
        {
            public readonly T Value;
            public Unit(T value) { Value = value; }
            public U MapTo<U>() { return MapFunc<T, U>.Instance(Value); }
        }
        public static class Extensions
        {
            public static Unit<T> Unit<T>(this T source) { return new Unit<T>(source); }
        }
        // Test
        public class Foo
        {
            public string Bar { get; set; }
            public string Baz { get; set; }
        }
        class Program
        {
            static void Main(string[] args)
            {
                var obj = new { Bar = "My Name", Baz = "Some other data" };
                //var foo = new Foo { Bar = obj.Bar, Baz = obj.Baz };
                var foo = obj.Unit().MapTo<Foo>();
            }
        }
    }
    
    使用系统;
    使用System.Linq;
    使用System.Linq.Expressions;
    命名空间测试
    {
    公共静态类Utils
    {
    公共静态函数CreateMapFunc()
    {
    var source=Expression.Parameter(typeof(TInput),“source”);
    var body=Expression.MemberInit(Expression.New(typeof(TOutput)),
    Select(p=>Expression.Bind(typeof(TOutput).GetProperty(p.Name),Expression.Property(source,p));
    var expr=Expression.Lambda(body,source);
    返回expr.Compile();
    }
    }
    公共静态类MapFunc
    {
    public static readonly Func Instance=Utils.CreateMapFunc();
    }
    公共结构单元
    {
    公共只读T值;
    公共单位(T值){value=value;}
    public U MapTo(){返回MapFunc.Instance(Value);}
    }
    公共静态类扩展
    {
    公共静态单元单元(此T源){返回新单元(源);}
    }
    //试验
    公开课Foo
    {
    公共字符串条{get;set;}
    公共字符串Baz{get;set;}
    }
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    var obj=new{Bar=“我的名字”,Baz=“其他一些数据”};
    //var foo=newfoo{Bar=obj.Bar,Baz=obj.Baz};
    var foo=obj.Unit().MapTo();
    }
    }
    }
    
    如果有人对其工作方式感兴趣:

    主要部分是
    CreateMapFunc
    函数,它使用
    MemberInitExpression
    构建和编译lambda表达式。它实际上应该是
    MapFunc
    类中的一个私有函数——我把它放在一个单独的类中,只是为了显示原始问题的答案

    MapFunc
    类是一个单例,充当已编译函数委托的缓存


    Unit
    充当中间者,并且(与扩展方法一起)需要允许推断传递的匿名对象的类型并仅指定目标类型。

    不清楚这里的上下文是什么-这是否已经是一个接受匿名类型作为类型参数的通用方法,以及
    typeof(Foo)
    作为参数?顺便说一句,找出这类操作的最简单方法是将lambda表达式编译到表达式树中,然后对其进行反编译。第一部分:该方法类似于“T MapFrom(object obj)”,其中保证对象始终是相同的匿名对象。第二部分:好主意。我现在就试试。为什么不创建一次映射委托,然后重用它呢?一定要试试FastMapper/Mapster。它们生成一个动态IL来映射对象,因此性能比自动映射好一个数量级。很好!这就是我所希望的用法。