using System.Linq.Dynamic.Core;
using System.Reflection.Emit;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
public static void Main()
DataTable dt1 = new DataTable("Customers");
dt1.Columns.Add("CustomerID", typeof(int));
dt1.Columns.Add("Name", typeof(string));
dt1.Columns.Add("City", typeof(string));
dt1.Rows.Add(1, "Alice", "New York");
dt1.Rows.Add(2, "Bob", "Los Angeles");
dt1.Rows.Add(3, "Charlie", "Seattle");
dt1.Rows.Add(4, "John", "Seattle");
.AsDynamicTypedQueryable()
foreach (var element in filtered) {
Console.WriteLine(element["Name"] + " " + element["CustomerID"]);
if (element["Name"] == "Bob") {
element["CustomerID"] = 0;
Console.WriteLine("--------------");
.AsDynamicTypedQueryable()
foreach (var element in filtered2) {
Console.WriteLine(element["Name"] + " " + element["CustomerID"]);
DataTable anotherDt = new DataTable("Customers12");
anotherDt.Columns.Add("CustomerID", typeof(int));
anotherDt.Columns.Add("Name", typeof(string));
anotherDt.Columns.Add("City", typeof(string));
anotherDt.Columns.Add("Age", typeof(int));
anotherDt.Rows.Add(1, "Alice", "New York", 42);
anotherDt.Rows.Add(2, "Bob", "Los Angeles", 45);
anotherDt.Rows.Add(3, "Charlie", "Seattle", 46);
anotherDt.Rows.Add(4, "John", "Seattle", 47);
anotherDt.Rows.Add(5, "Travis", "New Mexico", 47);
Console.WriteLine("--------------");
var filtered3 = anotherDt
.AsDynamicTypedQueryable()
.Where("City.Contains(\"New\")")
.Select("new (CustomerID, Name, Age)")
Console.WriteLine("------------");
foreach (var element in filtered3) {
Console.WriteLine(element.ToString());
public static class DynamicTypeDataTableExtensions {
public static IQueryable AsDynamicTypedQueryable(this DataTable dt) {
Type dynamicType = GetOrCreateTypeFromDataTable(dt);
var methodInfo = s_getLazyTypedEnumerable
.MakeGenericMethod(dynamicType);
var result = (IEnumerable)methodInfo.Invoke(null, new object[] { dt });
return result.AsQueryable();
private static MethodInfo s_getLazyTypedEnumerable = typeof(DynamicTypeDataTableExtensions)
.GetMethod(nameof(GetLazyTypedEnumerable), BindingFlags.Static | BindingFlags.NonPublic);
private static IEnumerable<T> GetLazyTypedEnumerable<T>(DataTable dt) {
var dataRowFieldInfo = typeof(T).GetField("DataRow");
foreach (DataRow row in dt.Rows) {
var obj = (T)Activator.CreateInstance(typeof(T));
dataRowFieldInfo.SetValue(obj, row);
private static ConcurrentDictionary<string, Type> s_Dictionary =
new ConcurrentDictionary<string, Type>();
private static Type GetOrCreateTypeFromDataTable(DataTable dt) {
var sb = new StringBuilder();
foreach (DataColumn column in dt.Columns) {
sb.Append(column.ColumnName);
sb.Append(column.DataType.FullName);
var signature = sb.ToString();
return s_Dictionary.GetOrAdd(signature, CreateDataRowHolderType(dt));
private static MethodInfo s_fieldExtensionMethod = typeof(DataRowExtensions).
new[] { typeof(DataRow), typeof(string) });
private static Type CreateDataRowHolderType(DataTable dt) {
var typeBuilder = GetTypeBuilder("DynamicRowType_" + Guid.NewGuid().ToString());
var fieldBuilder = typeBuilder.DefineField("DataRow", typeof(DataRow), FieldAttributes.Public);
foreach (DataColumn column in dt.Columns) {
var columnType = column.DataType;
var columnName = column.ColumnName;
var propBuilder = typeBuilder.DefineProperty(columnName, PropertyAttributes.HasDefault, columnType, null);
var getterMethod = typeBuilder.DefineMethod("get_" + columnName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
columnType, Type.EmptyTypes);
var getterIL = getterMethod.GetILGenerator();
getterIL.Emit(OpCodes.Ldarg_0);
getterIL.Emit(OpCodes.Ldfld, fieldBuilder);
getterIL.Emit(OpCodes.Ldstr, column.ColumnName);
var genericFieldMethod = s_fieldExtensionMethod.MakeGenericMethod(columnType);
getterIL.Emit(OpCodes.Call, genericFieldMethod);
getterIL.Emit(OpCodes.Ret);
propBuilder.SetGetMethod(getterMethod);
return typeBuilder.CreateType();
private static readonly ModuleBuilder ModuleBuilder = AssemblyBuilder
.DefineDynamicAssembly(new AssemblyName("DynamicTypesAssembly"), AssemblyBuilderAccess.Run)
.DefineDynamicModule("MainModule");
private static TypeBuilder GetTypeBuilder(string typeName) {
return ModuleBuilder.DefineType(typeName,
TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass |
TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout,