تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
كيفية تحويل DataTable إلى Object List
#1
كاتب الموضوع : Islam Ibrahim

السلام عليكم ورحمة الله وبركاته

في موضوع سابق للأخ أبو عابد عن كيفية تحويل DataTable إلى List(Of Object) أثار هذا الموضوع اهتمامي وقررت بناءًا على المعلومات التي أملك بالإضافة إلى مكتبة MSDN إيجاد كيفية لحل هذا اللغز,وأعتقد أنني وصلت للحل الأقرب باستخدام Reflection بحيث في المثال التالي سأقوم بإنشاء نوع جديد ديناميكيًا إنظلاقاً من المعلومات الموجودة في كائن DataTable.

قمت بكتابة دالتين الأولى GetTableType لإنشاء نوع جديد إنطلاقاً من ال DataTable, ودالة أخرى ToObjectList للحصول على جميع البيانات داخل DataTable وإضافتها لل List, طبعاً استخدمت ال List(Of Object) لأن المترجم لن يستطيع عمل Initializing ل List(Of T) وهو لا يعرف أي معلومات عن هذا النوع الجديد لأني أقوم بتعريفه باستخدام فئات الإنعكاس Reflection وبالتحديد باستخدام الكلاس Emit.TypeBuilder وبعص الفئات المساعدة مثل FieldBuilder, و PropertyBuilder بالإضافة لل ILGenerator. ولتعريف كائنات جديدة من هذا النوع الجديد سنحتاج لاستخدام الدالة Activator.CreateInstance, ومن ثم لتمرير القيم لخصائص تلك الكائنات الجديدة سنستخدم الدالة Type.InvokeMember.

عيب هذه الطريقة أنها بطيئة لأننا سنظطر للتعامل مع الربط المتأخر Late Binding للحصول على خصائص الكائن الذي نريده بمعلومية إسم العمود في الجدول, كما أن Intellisence في هذه الحالة لن يكون مدعوم هو الآخر.

هذا هو نص الدالتين, مع العلم لم أقم بإضافة أي كود للتحقق من صلاحية البيانات المدخلة وأترك المجال لكم وبالتأكيد النوع الجديد الذي سيتم إنشاؤه ستقبل خصائصه نفس نوع البيانات الخاص بالعمود في DataTable , وبالتأكيد يمكن استخدام هذه الطريقة مع أي DataTable:



كود :
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Module DataTableExtensions

<Extension()> Public Function GetTableType(ByVal DTable As DataTable) As Type

' Create needed TypeBuilder helpers
Dim myDomain As AppDomain = Thread.GetDomain()
Dim myAsmName As New AssemblyName("Anonymous")
Dim myAsmBuilder As AssemblyBuilder = _
myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run)

Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name)
Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType(DTable.TableName, TypeAttributes.Public)

For Each col As DataColumn In DTable.Columns

Dim PropertyName = col.ColumnName
Dim PropertyType = col.DataType

Dim PropertyFieldBuilder As FieldBuilder = myTypeBuilder.DefineField("_" & PropertyName.ToLower, _
PropertyType, FieldAttributes.Private)

Dim PBuilder As PropertyBuilder = _
myTypeBuilder.DefineProperty(PropertyName, PropertyAttributes.HasDefault, col.DataType, Nothing)

Dim getSetAttr As MethodAttributes = _
MethodAttributes.Public Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig

Dim getPropertyBuilder As MethodBuilder = _
myTypeBuilder.DefineMethod("get" & PropertyName, getSetAttr, col.DataType, Type.EmptyTypes)

' Constructing IL Code for get and set Methods.
Dim GetPropGenerator As ILGenerator = getPropertyBuilder.GetILGenerator()

GetPropGenerator.Emit(OpCodes.Ldarg_0)
GetPropGenerator.Emit(OpCodes.Ldfld, PropertyFieldBuilder)
GetPropGenerator.Emit(OpCodes.Ret)

Dim setPropertyBuulder As MethodBuilder = _
myTypeBuilder.DefineMethod("set_" & PropertyName, getSetAttr, Nothing, New Type() {col.DataType})

Dim SetPropGenerator As ILGenerator = setPropertyBuulder.GetILGenerator()

SetPropGenerator.Emit(OpCodes.Ldarg_0)
SetPropGenerator.Emit(OpCodes.Ldarg_1)
SetPropGenerator.Emit(OpCodes.Stfld, PropertyFieldBuilder)
SetPropGenerator.Emit(OpCodes.Ret)

PBuilder.SetGetMethod(getPropertyBuilder)
PBuilder.SetSetMethod(setPropertyBuulder)

Next

Dim objCtor As ConstructorInfo = GetType(Object).GetConstructor(New Type(-1) {})
Dim pointCtor As ConstructorBuilder = myTypeBuilder.DefineConstructor(MethodAttributes.Public, _
CallingConventions.Standard, Type.EmptyTypes)

Dim ctorIL As ILGenerator = pointCtor.GetILGenerator()

' Constructing IL Code for the Type Constructor.
ctorIL.Emit(OpCodes.Ldarg_0)
ctorIL.Emit(OpCodes.Call, objCtor)
ctorIL.Emit(OpCodes.Ret)

Return myTypeBuilder.CreateType()

End Function

<Extension()> _
Function ToObjectList(ByVal DTable As DataTable) As List(Of Object)

Dim list As New List(Of Object)
Dim tabletype As Type = DTable.GetTableType

For i = 0 To DTable.Rows.Count - 1
' Create an Instance of the Type for each row in DataTable
Dim ThisRow = Activator.CreateInstance(tabletype)
For j = 0 To DTable.Columns.Count - 1
tabletype.InvokeMember(DTable.Columns(j).ColumnName, BindingFlags.SetProperty, Nothing, _
ThisRow, New Object() {DTable.Rows(i).Item(j)})

Next
list.Add(ThisRow)

Next

Return list
End Function

End Module
طبعًا المستخدم بالتأكيد لابد له من معرفة أسماء الأعمدة وإلا لن يستطيع الإستفادة بهذا الكود.

بالتوفيق
}}}
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  شرح كيفية برمجة( مثال نسخ الملفات من مكان انت تحدده الى مكان انت تحدده بامتداد انت تحدده) سعود 5 8,117 04-09-19, 04:32 AM
آخر رد: سعود
  شرح كيفية صنع محرر html واستخدامه كـ dll سعود 6 6,030 26-08-13, 09:21 PM
آخر رد: Sajad
  طريقة تحويل صفحة في ملف Excel إلى DataSet RaggiTech 0 2,718 17-10-12, 10:09 PM
آخر رد: RaggiTech
  كيفية عمل صورة - مدورة - Rouded PictureBox ! RaggiTech 0 2,912 17-10-12, 09:55 PM
آخر رد: RaggiTech
  كيفية عمل String عشوائي ! RaggiTech 0 2,707 17-10-12, 09:54 PM
آخر رد: RaggiTech
  فائدة - كيفية عمل Ping RaggiTech 0 3,574 17-10-12, 09:00 PM
آخر رد: RaggiTech
  طريقة تحويل الصور الملونه الي صور ابيض واسود RaggiTech 0 3,920 17-10-12, 08:43 PM
آخر رد: RaggiTech
  مثال - تحويل التاريخ من ميلادي الى هجري وبالعكس في الفيجول دوت نت 2008 RaggiTech 0 4,716 17-10-12, 08:34 PM
آخر رد: RaggiTech
  كيفية ادارة صورة 360 درجة RaggiTech 0 2,238 17-10-12, 07:24 PM
آخر رد: RaggiTech
  للمبتدئين كيفية صنع فورم على شكل قلب او دائرة او متقاطعات او ما شابه مثال مع شرح مبسط RaggiTech 0 2,563 17-10-12, 07:15 PM
آخر رد: RaggiTech

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم