EF使用动态类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Collections;
using System.Reflection.Emit;
using System.Reflection;
 
namespace Demo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string connectionString = 
              "Server=(local); Integrated Security=true; Database=master";
            using (DbContext context = new DbContext(connectionString))
            {
                TypeBuilder builder = Program.CreateTypeBuilder(
                    "MyDynamicAssembly", "MyModule", "MyType");
                Program.CreateAutoImplementedProperty(builder, "name", typeof(string));
                Program.CreateAutoImplementedProperty(builder, "type", typeof(string));
                Program.CreateAutoImplementedProperty(builder, "id", typeof(int));
 
                Type resultType = builder.CreateType();
 
                dynamic queryResult = context.Database.SqlQuery(
                    resultType, "SELECT * FROM sys.sysobjects");
 
                Console.WriteLine("{0,20} {1,4} {2,10}", "Name", "Type", "ID");
                foreach (dynamic item in queryResult)
                {
                    Console.WriteLine("{0,10} {1,4} {2,10}", item.name, item.type, item.id);
                }
            }
 
            Console.ReadKey();
        }
 
        public static TypeBuilder CreateTypeBuilder(
            string assemblyName, string moduleName, string typeName)
        {
            TypeBuilder typeBuilder = AppDomain
                .CurrentDomain
                .DefineDynamicAssembly(new AssemblyName(assemblyName), 
                                       AssemblyBuilderAccess.Run)
                .DefineDynamicModule(moduleName)
                .DefineType(typeName, TypeAttributes.Public);
            typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
            return typeBuilder;
        }
 
        public static void CreateAutoImplementedProperty(
            TypeBuilder builder, string propertyName, Type propertyType)
        {
            const string PrivateFieldPrefix = "m_";
            const string GetterPrefix = "get_";
            const string SetterPrefix = "set_";
 
            // Generate the field.
            FieldBuilder fieldBuilder = builder.DefineField(
                string.Concat(PrivateFieldPrefix, propertyName), 
                              propertyType, FieldAttributes.Private);
 
            // Generate the property
            PropertyBuilder propertyBuilder = builder.DefineProperty(
                propertyName, PropertyAttributes.HasDefault, propertyType, null);
 
            // Property getter and setter attributes.
            MethodAttributes propertyMethodAttributes =
                MethodAttributes.Public | MethodAttributes.SpecialName | 
                MethodAttributes.HideBySig;
 
            // Define the getter method.
            MethodBuilder getterMethod = builder.DefineMethod(
                string.Concat(GetterPrefix, propertyName), 
                propertyMethodAttributes, propertyType, Type.EmptyTypes);
 
            // Emit the IL code.
            // ldarg.0
            // ldfld,_field
            // ret
            ILGenerator getterILCode = getterMethod.GetILGenerator();
            getterILCode.Emit(OpCodes.Ldarg_0);
            getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
            getterILCode.Emit(OpCodes.Ret);
 
            // Define the setter method.
            MethodBuilder setterMethod = builder.DefineMethod(
                string.Concat(SetterPrefix, propertyName), 
                propertyMethodAttributes, null, new Type[] { propertyType });
 
            // Emit the IL code.
            // ldarg.0
            // ldarg.1
            // stfld,_field
            // ret
            ILGenerator setterILCode = setterMethod.GetILGenerator();
            setterILCode.Emit(OpCodes.Ldarg_0);
            setterILCode.Emit(OpCodes.Ldarg_1);
            setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
            setterILCode.Emit(OpCodes.Ret);
 
            propertyBuilder.SetGetMethod(getterMethod);
            propertyBuilder.SetSetMethod(setterMethod);
        }
    }
}
  /// <summary>
        /// Reads database schema from query, generates assembly in the memory, and returns dynamic object
        /// </summary>
        public static System.Collections.IEnumerable DynamicSqlQuery(this Database database, string sql, params object[] parameters)
        {
            TypeBuilder builder = DynamicMapper.createTypeBuilder(
                    "MyDynamicAssembly", "MyDynamicModule", "MyDynamicType");
 
            using (System.Data.IDbCommand command = database.Connection.CreateCommand())
            {
                try
                {
                    database.Connection.Open();
                    command.CommandText = sql;
                    command.CommandTimeout = command.Connection.ConnectionTimeout;
                    foreach (var param in parameters)
                    {
                        command.Parameters.Add(param);
                    }
 
                    using (System.Data.IDataReader reader = command.ExecuteReader())
                    {
                        var schema = reader.GetSchemaTable();
                        foreach (System.Data.DataRow row in schema.Rows)
                        {
                            string name = (string)row["ColumnName"];
                            Type type = (Type)row["DataType"];
                            DynamicMapper.createAutoImplementedProperty(builder, name, type);
                        }
                    }
                }
                finally
                {
                    database.Connection.Close();
                    command.Parameters.Clear();
                }
            }
 
            Type resultType = builder.CreateType();
 
            return database.SqlQuery(resultType, sql, parameters);
        }
 
        private static TypeBuilder createTypeBuilder(
            string assemblyName, string moduleName, string typeName)
        {
            TypeBuilder typeBuilder = AppDomain
                .CurrentDomain
                .DefineDynamicAssembly(new AssemblyName(assemblyName),
                                       AssemblyBuilderAccess.Run)
                .DefineDynamicModule(moduleName)
                .DefineType(typeName, TypeAttributes.Public);
            typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
            return typeBuilder;
        }
 
        private static void createAutoImplementedProperty(
            TypeBuilder builder, string propertyName, Type propertyType)
        {
            const string PrivateFieldPrefix = "m_";
            const string GetterPrefix = "get_";
            const string SetterPrefix = "set_";
 
            // Generate the field.
            FieldBuilder fieldBuilder = builder.DefineField(
                string.Concat(PrivateFieldPrefix, propertyName),
                              propertyType, FieldAttributes.Private);
 
            // Generate the property
            PropertyBuilder propertyBuilder = builder.DefineProperty(
                propertyName, PropertyAttributes.HasDefault, propertyType, null);
 
            // Property getter and setter attributes.
            MethodAttributes propertyMethodAttributes =
                MethodAttributes.Public | MethodAttributes.SpecialName |
                MethodAttributes.HideBySig;
 
            // Define the getter method.
            MethodBuilder getterMethod = builder.DefineMethod(
                string.Concat(GetterPrefix, propertyName),
                propertyMethodAttributes, propertyType, Type.EmptyTypes);
 
            // Emit the IL code.
            // ldarg.0
            // ldfld,_field
            // ret
            ILGenerator getterILCode = getterMethod.GetILGenerator();
            getterILCode.Emit(OpCodes.Ldarg_0);
            getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
            getterILCode.Emit(OpCodes.Ret);
 
            // Define the setter method.
            MethodBuilder setterMethod = builder.DefineMethod(
                string.Concat(SetterPrefix, propertyName),
                propertyMethodAttributes, null, new Type[] { propertyType });
 
            // Emit the IL code.
            // ldarg.0
            // ldarg.1
            // stfld,_field
            // ret
            ILGenerator setterILCode = setterMethod.GetILGenerator();
            setterILCode.Emit(OpCodes.Ldarg_0);
            setterILCode.Emit(OpCodes.Ldarg_1);
            setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
            setterILCode.Emit(OpCodes.Ret);
 
            propertyBuilder.SetGetMethod(getterMethod);
            propertyBuilder.SetSetMethod(setterMethod);
        }        
    }



public static class DynamicMapper
{
    private static Dictionary<string, Type> baseEntityTypesByType = new Dictionary<string, Type>();
 
    public static System.Collections.IEnumerable DynamicSqlQuery(this Database database, string sql, params object[] parameters)
    {
 
        Type resultType;
 
        if (baseEntityTypesByType.TryGetValue(sql, out resultType))
        {
            Console.WriteLine("Inside Got the Type");
            if (parameters != null)
                return database.SqlQuery(resultType, sql, parameters);
            return database.SqlQuery(resultType, sql);
        }
 
        TypeBuilder builder = DynamicMapper.createTypeBuilder(
                "MyDynamicAssembly", "MyDynamicModule", "MyDynamicType");
 
        using (System.Data.IDbCommand command = database.Connection.CreateCommand())
        {
            try
            {
                database.Connection.Open();
                command.CommandText = sql;
                command.CommandTimeout = command.Connection.ConnectionTimeout;
                if (parameters != null)
                {
                    foreach (var param in parameters)
                    {
                        command.Parameters.Add(param);
                    }
                }
 
                using (System.Data.IDataReader reader = command.ExecuteReader())
                {
                    var schema = reader.GetSchemaTable();
                    foreach (System.Data.DataRow row in schema.Rows)
                    {
                        string name = (string)row["ColumnName"];
                        Type type = (Type)row["DataType"];
                        var allowNull = (bool) row["AllowDBNull"];
                        if (allowNull)
                        {
                            type = GetNullableType(type);
                        }
                        DynamicMapper.createAutoImplementedProperty(builder, name, type);
                    }
                }
            }
            finally
            {
                database.Connection.Close();
                command.Parameters.Clear();
            }
        }
 
        resultType = builder.CreateType();
        baseEntityTypesByType[sql] = resultType;
 
        if (parameters!=null)
        return database.SqlQuery(resultType, sql, parameters);
 
        return database.SqlQuery(resultType,sql);
    }
 
    private static TypeBuilder createTypeBuilder(
        string assemblyName, string moduleName, string typeName)
    {
        TypeBuilder typeBuilder = AppDomain
            .CurrentDomain
            .DefineDynamicAssembly(new AssemblyName(assemblyName),
                                   AssemblyBuilderAccess.Run)
            .DefineDynamicModule(moduleName)
            .DefineType(typeName, TypeAttributes.Public);
        typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
        return typeBuilder;
    }
 
    private static void createAutoImplementedProperty(
        TypeBuilder builder, string propertyName, Type propertyType)
    {
        const string PrivateFieldPrefix = "m_";
        const string GetterPrefix = "get_";
        const string SetterPrefix = "set_";
 
        // Generate the field.
        FieldBuilder fieldBuilder = builder.DefineField(
            string.Concat(PrivateFieldPrefix, propertyName),
                          propertyType, FieldAttributes.Private);
 
        // Generate the property
        PropertyBuilder propertyBuilder = builder.DefineProperty(
            propertyName, PropertyAttributes.HasDefault, propertyType, null);
 
        // Property getter and setter attributes.
        MethodAttributes propertyMethodAttributes =
            MethodAttributes.Public | MethodAttributes.SpecialName |
            MethodAttributes.HideBySig;
 
        // Define the getter method.
        MethodBuilder getterMethod = builder.DefineMethod(
            string.Concat(GetterPrefix, propertyName),
            propertyMethodAttributes, propertyType, Type.EmptyTypes);
 
        // Emit the IL code.
        // ldarg.0
        // ldfld,_field
        // ret
        ILGenerator getterILCode = getterMethod.GetILGenerator();
        getterILCode.Emit(OpCodes.Ldarg_0);
        getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
        getterILCode.Emit(OpCodes.Ret);
 
        // Define the setter method.
        MethodBuilder setterMethod = builder.DefineMethod(
            string.Concat(SetterPrefix, propertyName),
            propertyMethodAttributes, null, new Type[] { propertyType });
 
        // Emit the IL code.
        // ldarg.0
        // ldarg.1
        // stfld,_field
        // ret
        ILGenerator setterILCode = setterMethod.GetILGenerator();
        setterILCode.Emit(OpCodes.Ldarg_0);
        setterILCode.Emit(OpCodes.Ldarg_1);
        setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
        setterILCode.Emit(OpCodes.Ret);
 
        propertyBuilder.SetGetMethod(getterMethod);
        propertyBuilder.SetSetMethod(setterMethod);
    }
 
    public static Type GetNullableType(Type TypeToConvert)
    {
        // Abort if no type supplied
        if (TypeToConvert == null)
            return null;
 
        // If the given type is already nullable, just return it
        if (IsTypeNullable(TypeToConvert))
            return TypeToConvert;
 
        // If the type is a ValueType and is not System.Void, convert it to a Nullable<Type>
        if (TypeToConvert.IsValueType && TypeToConvert != typeof(void))
            return typeof(Nullable<>).MakeGenericType(TypeToConvert);
 
        // Done - no conversion
        return null;
    }
    public static bool IsTypeNullable(Type TypeToTest)
    {
        // Abort if no type supplied
        if (TypeToTest == null)
            return false;
 
        // If this is not a value type, it is a reference type, so it is automatically nullable
        //  (NOTE: All forms of Nullable<T> are value types)
        if (!TypeToTest.IsValueType)
            return true;
 
        // Report whether TypeToTest is a form of the Nullable<> type
        return TypeToTest.IsGenericType && TypeToTest.GetGenericTypeDefinition() == typeof(Nullable<>);
    }
 
}
 
原文地址:https://www.cnblogs.com/xiajing12345/p/7307724.html