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 :