net動態對象轉匿名對象

1、參考: http://blog.zhaojie.me/2010/05/generate-dynamic-method-with-expression-tree-in-dot-net-4.html

2、主要類

public static class AnonymousFactory
    {
        //private static ConcurrentDictionary<Type, Type> s_dynamicTypes = new ConcurrentDictionary<Type, Type>();
        //private static Func<dynamic, Type> s_dynamicTypeCreator = new Func<dynamic, Type>(CreateAnonymousType);

        //private static ConcurrentDictionary<Type, Func<object, object>> s_dynamicEntityFactories =
        //new ConcurrentDictionary<Type, Func<object, object>>();
        //private static Func<dynamic, Func<object, object>> s_factoryCreator = new Func<dynamic, Func<object, object>>(DynamicFactoryCreator);

        public static object ToAnonymousRef(dynamic entity)
        {
            var entityType = entity.GetType();
            //var dynamicType = s_dynamicTypes.GetOrAdd(entityType, s_dynamicTypeCreator(entity));

            var dynamicType = CreateAnonymousType(entity);
            var dynamicObject = Activator.CreateInstance(dynamicType);
            var dict = (IDictionary<string, object>)entity;
            foreach (var key in dict.Keys)
            {
                var value = dict[key];
                dynamicType.GetField(key).SetValue(dynamicObject, value);
            }

            return dynamicObject;
        }

        public static object ToAnonymous(dynamic entity)
        {
            var entityType = entity.GetType();
            //var factory = s_dynamicEntityFactories.GetOrAdd(entityType, s_factoryCreator(entity));
            var factory = DynamicFactoryCreator(entity);
            return factory(entity);
        }

        public static object ToAnonymousNoParam(dynamic entity)
        {
            var entityType = entity.GetType();
            //var factory = s_dynamicEntityFactories.GetOrAdd(entityType, s_factoryCreator(entity));
            var factory = DynamicFactoryCreatorNoParam(entity);
            return factory();
        }

        private static Type CreateAnonymousType(dynamic entity)
        {
            var guid = Guid.NewGuid();
            string strDynamicModuleName = "Anonymous_" + guid;
            string strDynamicClassName = "<>Anonymous_" + guid;

            AppDomain currentDomain = System.AppDomain.CurrentDomain;
            AssemblyName assemblyName = new AssemblyName(strDynamicModuleName);
            AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(strDynamicModuleName);
            TypeBuilder typeBuilder = moduleBuilder.DefineType(strDynamicClassName, TypeAttributes.Public);

            var dict = (IDictionary<string, object>)entity;
            foreach (var key in dict.Keys)
            {
                typeBuilder.DefineField(key, dict[key].GetType(), FieldAttributes.Public);
            }

            return typeBuilder.CreateType();
        }

        public static void TestInsert()
        {
            Func<int, List<int>> t6 = t => { return new List<int> { t, 2 }; };
            // define the parameter
            var parameterExpr = Expression.Parameter(typeof(int), "t");

            // collect the body
            var bodyExprs = new List<Expression>();
            var anonymousType = typeof(List<int>);

            // code: var AnonymousEntity = new DynamicType();
            var anonymousEntityExpr = Expression.Variable(anonymousType, "AnonymousEntity");
            var newAnonymousTypeExpr = Expression.New(anonymousType);
            var assignDynamicEntityExpr = Expression.Assign(anonymousEntityExpr, newAnonymousTypeExpr);
            bodyExprs.Add(assignDynamicEntityExpr);

            MethodInfo addMethod = anonymousType.GetMethod("Add");
            bodyExprs.Add(Expression.Call(anonymousEntityExpr, addMethod, parameterExpr));
            bodyExprs.Add(Expression.Call(anonymousEntityExpr, addMethod, Expression.Constant(2)));

            // code: return (object)dynamicEntity;
            var castResultExpr = Expression.Convert(anonymousEntityExpr, typeof(List<int>));
            bodyExprs.Add(castResultExpr);

            var methodBodyExpr = Expression.Block(
                typeof(List<int>), /* return type */
                new[] { anonymousEntityExpr }, /* local variables */
                bodyExprs /* body expressions */);

            // code: entity => { ... }
            var lambdaExpr = Expression.Lambda<Func<int, List<int>>>(methodBodyExpr, parameterExpr);

            var testFun = lambdaExpr.Compile();
            var result = testFun(5);
        }

        private static Func<object, object> DynamicFactoryCreator(dynamic entity)
        {
            dynamic expando = new System.Dynamic.ExpandoObject(); //動態類型字段 可讀可寫
            expando.Id = 1;
            expando.Name = "Test";
            var t2 = new { expando.Id, expando.Name };

            Func<object, object> buildEntity = t =>
            {
                return new
                {
                    expando.Id,
                    expando.Name
                };
            };

            var anonymousType = CreateAnonymousType(entity);

            // define the parameter
            var parameterExpr = Expression.Parameter(typeof(object), "entity");

            // collect the body
            var bodyExprs = new List<Expression>();

            // code: var AnonymousEntity = new DynamicType();
            var anonymousEntityExpr = Expression.Variable(anonymousType, "AnonymousEntity");
            var newAnonymousTypeExpr = Expression.New(anonymousType);
            var assignDynamicEntityExpr = Expression.Assign(anonymousEntityExpr, newAnonymousTypeExpr);
            bodyExprs.Add(assignDynamicEntityExpr);

            // generate code for fields' assignments
            var dict = (IDictionary<string, object>)entity;
            foreach (var key in dict.Keys)
            {
                var fieldExpr = Expression.Field(anonymousEntityExpr, key);
                var constExpr = Expression.Constant(dict[key]);
                var assignFieldExpr = Expression.Assign(fieldExpr, constExpr);

                bodyExprs.Add(assignFieldExpr);
            }

            // code: return (object)dynamicEntity;
            var castResultExpr = Expression.Convert(anonymousEntityExpr, typeof(object));
            bodyExprs.Add(castResultExpr);

            // code: { ... }
            var methodBodyExpr = Expression.Block(
                typeof(object), /* return type */
                new ParameterExpression[] { anonymousEntityExpr }, /* local variables */
                bodyExprs /* body expressions */);

            // code: entity => { ... }
            var lambdaExpr = Expression.Lambda<Func<object, object>>(methodBodyExpr, parameterExpr);

            return lambdaExpr.Compile();
        }

        private static Func<object> DynamicFactoryCreatorNoParam(dynamic entity)
        {
            dynamic expando = new System.Dynamic.ExpandoObject(); //動態類型字段 可讀可寫
            expando.Id = 1;
            expando.Name = "Test";
            var t2 = new { expando.Id, expando.Name };

            Func<object> buildEntity = () =>
            {
                return new
                {
                    expando.Id,
                    expando.Name
                };
            };

            var anonymousType = CreateAnonymousType(entity);

            // define the parameter
            var parameterExpr = Expression.Parameter(typeof(object), "entity");

            // collect the body
            var bodyExprs = new List<Expression>();

            // code: var AnonymousEntity = new DynamicType();
            var anonymousEntityExpr = Expression.Variable(anonymousType, "AnonymousEntity");
            var newAnonymousTypeExpr = Expression.New(anonymousType);
            var assignDynamicEntityExpr = Expression.Assign(anonymousEntityExpr, newAnonymousTypeExpr);
            bodyExprs.Add(assignDynamicEntityExpr);

            // generate code for fields' assignments
            var dict = (IDictionary<string, object>)entity;
            foreach (var key in dict.Keys)
            {
                var fieldExpr = Expression.Field(anonymousEntityExpr, key);
                var constExpr = Expression.Constant(dict[key]);
                var assignFieldExpr = Expression.Assign(fieldExpr, constExpr);

                bodyExprs.Add(assignFieldExpr);
            }

            // code: return (object)dynamicEntity;
            var castResultExpr = Expression.Convert(anonymousEntityExpr, typeof(object));
            bodyExprs.Add(castResultExpr);

            // code: { ... }
            var methodBodyExpr = Expression.Block(
                typeof(object), /* return type */
                new ParameterExpression[] { anonymousEntityExpr }, /* local variables */
                bodyExprs /* body expressions */);

            // code: entity => { ... }
            var lambdaExpr = Expression.Lambda<Func<object>>(methodBodyExpr);

            return lambdaExpr.Compile();
        }
    }

3、調用

static void Main(string[] args)
        {
            dynamic expando = new System.Dynamic.ExpandoObject(); //動態類型字段 可讀可寫
            expando.Id = 1;
            expando.Name = "Test";
            var t2 = new { expando.Id, expando.Name };
            var t3 = AnonymousFactory.ToAnonymousRef(expando);
            var t4 = AnonymousFactory.ToAnonymous(expando);
            var t5 = AnonymousFactory.ToAnonymousNoParam(expando);
            AnonymousFactory.TestInsert();
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章