Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

LINQ To SQL Table -> DataTable, génération de code à la volée, V3

Suite à la nouvelle remarque de Jean-Baptiste, mon code devient finalement ceci :

namespace ConsoleApplication81

{

    class Program

    {

        static void Main(string[] args)

        {

            using (var context = new DataClasses1DataContext())

            {

                var dt = LinqTableToDataTableHelper<Category>.GetDataTableFromLINQTable(context.Categories);

            }

        }

    }

    public static class LinqTableToDataTableHelper<LTT>

            where LTT : class

    {

        private static Func<Table<LTT>, DataTable> _generatedMethodDelegate;

 

        public static DataTable GetDataTableFromLINQTable(Table<LTT> linqTable)

        {

            if (_generatedMethodDelegate == null)

                _generatedMethodDelegate = GenerateTableConverter().CreateDelegate(typeof(Func<Table<LTT>, DataTable>)) as Func<Table<LTT>, DataTable>;

            return _generatedMethodDelegate(linqTable);

        }

 

        public static DynamicMethod GenerateTableConverter()

        {

            var dynamicMethod = new DynamicMethod("Convert", typeof(DataTable), new Type[] { typeof(Table<LTT>) });

            var convertIlGenerator = dynamicMethod.GetILGenerator();

            convertIlGenerator.DeclareLocal(typeof(DataTable));

            convertIlGenerator.DeclareLocal(typeof(IEnumerator<LTT>));

            convertIlGenerator.DeclareLocal(typeof(LTT));

            convertIlGenerator.DeclareLocal(typeof(DataRow));

            var propertyValue = convertIlGenerator.DeclareLocal(typeof(object));

            convertIlGenerator.Emit(OpCodes.Ldarg_0);

            var convertIlGeneratorArgOkLabel = convertIlGenerator.DefineLabel();

            convertIlGenerator.Emit(OpCodes.Brtrue_S, convertIlGeneratorArgOkLabel);

            convertIlGenerator.Emit(OpCodes.Newobj, typeof(ArgumentException).GetConstructor(new Type[0]));

            convertIlGenerator.Emit(OpCodes.Throw);

            convertIlGenerator.MarkLabel(convertIlGeneratorArgOkLabel);

 

            convertIlGenerator.Emit(OpCodes.Newobj, typeof(DataTable).GetConstructor(new Type[0]));

            convertIlGenerator.Emit(OpCodes.Stloc_0);

            var properties = typeof(LTT).GetProperties().Where(p => p.GetAttribute<ColumnAttribute>() != null);

            foreach (var pi in properties)

            {

                convertIlGenerator.Emit(OpCodes.Ldloc_0);

                convertIlGenerator.Emit(OpCodes.Callvirt, typeof(DataTable).GetMethod("get_Columns"));

                convertIlGenerator.Emit(OpCodes.Ldstr, pi.Name);

                if (pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))

                    convertIlGenerator.Emit(OpCodes.Ldtoken, pi.PropertyType.GetGenericArguments()[0]);

                else

                    convertIlGenerator.Emit(OpCodes.Ldtoken, pi.PropertyType);

                convertIlGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }));

                convertIlGenerator.Emit(OpCodes.Callvirt, typeof(DataColumnCollection).GetMethod("Add", new Type[] { typeof(string), typeof(Type) }));

                convertIlGenerator.Emit(OpCodes.Pop);

            }

            var convertIlGeneratorEntitiesLoopLabel = convertIlGenerator.DefineLabel();

            convertIlGenerator.Emit(OpCodes.Ldarg_0);

            convertIlGenerator.Emit(OpCodes.Callvirt, typeof(IEnumerable<LTT>).GetMethod("GetEnumerator"));

            convertIlGenerator.Emit(OpCodes.Stloc_1);

            convertIlGenerator.MarkLabel(convertIlGeneratorEntitiesLoopLabel);

            convertIlGenerator.Emit(OpCodes.Ldloc_1);

            convertIlGenerator.Emit(OpCodes.Callvirt, typeof(IEnumerator).GetMethod("MoveNext"));

            var convertIlGeneratorEntitiesEndLoopLable = convertIlGenerator.DefineLabel();

            convertIlGenerator.Emit(OpCodes.Brfalse, convertIlGeneratorEntitiesEndLoopLable);

            convertIlGenerator.Emit(OpCodes.Ldloc_1);

            convertIlGenerator.Emit(OpCodes.Callvirt, typeof(IEnumerator<LTT>).GetMethod("get_Current"));

            convertIlGenerator.Emit(OpCodes.Stloc_2);

            convertIlGenerator.Emit(OpCodes.Ldloc_0);

            convertIlGenerator.Emit(OpCodes.Callvirt, typeof(DataTable).GetMethod("get_Rows"));

            convertIlGenerator.Emit(OpCodes.Ldloc_0);

            convertIlGenerator.Emit(OpCodes.Callvirt, typeof(DataTable).GetMethod("NewRow"));

            convertIlGenerator.Emit(OpCodes.Stloc_3);

            foreach (var pi in properties)

            {

                convertIlGenerator.Emit(OpCodes.Ldloc_2);

                convertIlGenerator.Emit(OpCodes.Callvirt, typeof(LTT).GetMethod("get_" + pi.Name, new Type[0]));

                if (pi.PropertyType.IsValueType)

                    convertIlGenerator.Emit(OpCodes.Box, pi.PropertyType);

                convertIlGenerator.Emit(OpCodes.Stloc, propertyValue);

                convertIlGenerator.Emit(OpCodes.Ldloc, propertyValue);

                var convertIlGeneratorNextPropertyLabel = convertIlGenerator.DefineLabel();

                convertIlGenerator.Emit(OpCodes.Brfalse_S, convertIlGeneratorNextPropertyLabel);

                convertIlGenerator.Emit(OpCodes.Ldloc_3);

                convertIlGenerator.Emit(OpCodes.Ldstr, pi.Name);

                convertIlGenerator.Emit(OpCodes.Ldloc, propertyValue);

                convertIlGenerator.Emit(OpCodes.Callvirt, typeof(DataRow).GetMethod("set_Item", new Type[] { typeof(string), typeof(object) }));

                convertIlGenerator.MarkLabel(convertIlGeneratorNextPropertyLabel);

            }

            convertIlGenerator.Emit(OpCodes.Ldloc_3);

            convertIlGenerator.Emit(OpCodes.Callvirt, typeof(DataRowCollection).GetMethod("Add", new Type[] { typeof(DataRow) }));

            convertIlGenerator.Emit(OpCodes.Br, convertIlGeneratorEntitiesLoopLabel);

            convertIlGenerator.MarkLabel(convertIlGeneratorEntitiesEndLoopLable);

            convertIlGenerator.Emit(OpCodes.Ldloc_0);

            convertIlGenerator.Emit(OpCodes.Ret);

 

            return dynamicMethod;

        }

    }

}

namespace System.Reflection

{

    public static class PropertyInfoExtension

    {

        public static T GetAttribute<T>(this PropertyInfo pi) where T : Attribute

        {

            object[] attributes = pi.GetCustomAttributes(typeof(T), true);

            if (attributes.Length == 0)

                return null;

            return attributes[0] as T;

        }

    }

}

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Publié lundi 14 avril 2008 17:49 par Matthieu MEZIL

Classé sous : , , , ,

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01