تقييم الموضوع :
  • 2 أصوات - بمعدل 5
  • 1
  • 2
  • 3
  • 4
  • 5
مقال: Reflection وكيفية استخدامها في برامجنا
#1
[ملحوظة: هذا الموضوع يناقش أغراض تعليمية فقط, ولا يمت بصلة بموضوع الهندسة العكسية.]


Reflection من التقنيات الهامة للدوت نت, وعن طريقها يستطيع أي برنامج جمع معلومات التعريف MetaData الخاصة به والتعامل معها, وتعتبر آلية قوية وفعالة للتعامل مع الكائنات وقت التشغيل, أدوات ال Reflection توجد ضمن مساحة الإسم System.Reflection, تتيح الفئات والواجهات الموجودة ضمن مساحة الاسم System.Reflection المبرمجين من مراقبة وجمع المعلومات حول نوع Type معيّن, وكذلك الوصول إلى الخصائص والدوال والإجراءات الخاصة بذلك النوع باستخدام الإجراء Invoke, يمكن من خلالها أيضا كتابة تطبيقات و برامج الهندسة العكسية, مستعرضات للفئات Class Viewers, أو محررات الخصائص Property Editors, سنناقش في هذا الموضوع الاستخدامات التالية لآلية Reflection, وهي:

  • بعض المفاهيم الأساسية
  • كيفية جمع بيانات التعريف MetaData حول تجميع Assembly معيّن , واستكشاف الأنواع التي يحتويها ذلك التجميع
  • الاستدعاء الديناميكي للإجراءات والخصائص وقت التشغيل RunTime
    باستخدام الربط المتأخر Late binding يمكن إنشاء مثيل كائن Object Instance من نوع معيّن واستدعاء الإجراءات والخصائص الخاصة به, بعد الكشف عنها.
  • إنشاء التجميعات والأنواع أثناء وقت التشغيل باستخدام مساحة الاسم System.Reflection.Emit
    وهذه هي الميزة الأكثر أهمية وفائدة في تقنية Reflection, حيث تساعد على إنشاء الأنواع والتجميعات أثناء وقت التشغيل من أجل إنجاز مهام معيّنة حسب الحاجة إليها, وحفظها على مساحات التخزين, واستخدامها كذلك أثناء وقت التشغيل, وتعتبر هذه الميزة مدخلاً لما يعرف بالذكاء الصناعي, ومع ذلك فإن لهذه التقنية مساوئ سنناقشها في بقية الموضوع.

بعض المفاهيم الأساسية:

System.Type: هذه الفئة أساسية ويمكن ان تمثل عدة أنواع, إما: الفئات, الواجهات المصفوفات, أوالتراقيم (هذه هي الأنواع التي تهمنا).

.NET Managed Module (وحدة نمطية مُدارة): هو إما ملف تنفيذي محمول Portable Executable أو ملف نوع Type DLL, قد تحتوي على فئة واحدة أو واجهة واحدة أو اكثر, يمكن ان تحتوي هذه الوحدة النمطية على اكثر من مساحة اسم NameSpace واحدة, ويمكن أن تشمل مساحة اسم واحدة على أكثر من وحدة نمطية.

واحدة او أكثر من الوحدات النمطية تشكل مجتمعة مايعرف بالـتجميع Assembly, لا يجب الخاط بين Module أو (وحدة التعليمات البرمجية) الخاصة بـ Visual Basic وبين الوحدة النمطية.

يمكن الحصول على وحدة نمطية بعد ترجمة التعليمات البرمجية باستخدام Visual Studio أو باستخدام اداة مترجم اللغة vbc.exe (Visual Basic compiler) او الأداة csc.exe ( CSharp compiler) والموجودة ضمن ادوات سطر الأوامر Visual Studio Command Line tools.

يمكن ربط أكثر من وحدة نمطية واحدة لتشكيل تجميع واحد باستخدام الأداة Al.exe (Assembly Linker), والمخطط التالي يوضح ذلك:

تتشكل كل وحدة نمطية أساساً من الأجزاء التالية:

  • PE Header: مثل اي ملف Win32 PE غير مدار, تحتوي الوحدات المدارة على PE header, يحتوي PE header على معلومات حول نوع الوحدة (مدارة او غير مدارة) + معلومات حول تاريخ بناء الوحدة + نوع CPU المستهدف (x86 او x64)
  • CLR Header: يحتوي على معلومات إصدار Framework المستهدف, ومعلومات حول دالة التنفيذ الرئيسية في الوحدة.
  • Metadata: هي ببساطة الواجهة الرئيسية التي تقوم بتعريف ووصف الأنواع وتقديم معلومات عنها عند إضافة الوحدة التي تحتويها كمرجع reference إلى تجميع آخر. تتلخص المعلومات التي تقدمها في: الإسم والإصدار والمفتاح العمومي Public Key, الأنواع المستخدمة, التجميعات المرتبطة, أذونات الأمان Security Permissions المطلوبة أثناء التشغيل, السمات Attributes.
  • تعليمات لغة Microsoft الوسيطة MSIL : عند تحويل الكود إلى ملف تنفيذي باستخدام Visual Studio او vbc.exe فإنه سيتم تحويل تلك الأكواد إلى لغة MSIL, والتي تعتمد على تنفيذ تعليماتها على شكل رصة Stack, تعتبر هذه اللغة مشتركة بين جميع لغات البرمجة التي تعتمد عليها الوت نت.

Application Domain (مجال التطبيق): هو البيئة التي يعمل عليها التطبيق حيث توفر تلك البيئة عزلاً لما يقوم به التطبيق عن باقي التطبيقات, تمكِّن الفئة AppDomain الوصول إلى مجال التطبيق الحالي, وتطبيق جملة من العمليات عليه.
الرد }}}
تم الشكر بواسطة: ابو ابراهيم , ابو ليلى
#2
الكشف عن التجميعات المرتبطة (المحملة) مع أحد التطبيق

أنشئ مشروع Console Application واستبدل محتويات Module1.vb بالكود التالي

كود C#

كود :
using System;
using System.Reflection ;


    class ReferencedAssemblies
    {
        [STAThread]
        static void Main(string[] args)
        {
            Assembly[] appAssemblies =
              System.AppDomain.CurrentDomain.GetAssemblies ();
            foreach (Assembly assembly in appAssemblies )
            {
                Console.WriteLine (assembly.FullName );
            }
            Console.ReadLine ();
        }
    }


كود VB

كود :
Imports System.Reflection
Namespace ReflectionDemo
    Class ReferencedAssemblies
        Private Shared Sub Main(ByVal args As String())
            Dim appAssemblies As Assembly() = System.AppDomain.CurrentDomain.GetAssemblies()
            For Each assembly As Assembly In appAssemblies
                Console.WriteLine(assembly.FullName)
            Next
            Console.ReadLine()
        End Sub
    End Class


يقوم الإجراءا GetAssemblies() أحد اعضاء الفئة AppDomain بإرجاع التجميعات التي قام البرنامج ReflectionDemo بتحميلها والناتج هو التجميعين ReflectionDemo و MsCorLib

عند تنفيذ البرنامج سيظهر في ال Console مايلي:

كود :
mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ReflectionDemo, Version=1.0.1882.29904, Culture=neutral, PublicKeyToken

الحصول على الأنواع الموجودة ضمن تجميع معيّن

أول ما يجب القيام به, هو تحميل التجميع ديناميكيا باستخدام الإجراء Assembly.Load().

كود VB
كود :
Dim LoadedAssembly As Assembly = Assembly.Load("mscorlib.dll")
كود C#
كود :
Assembly LoadedAssembly = Assembly.Load("mscorlib.dll");


بعد تحميل التجميع, يمكن الإجراء GetTypes() للحصول على مصفوفة من النوع Type


كود VB
كود :
Dim ExistingTypes As System.Type() = LoadedAssembly.GetTypes()


كود C#
كود :
System.Type[] ExistingTypes = LoadedAssembly.GetTypes ();


الأنواع العائدة يمكن أن تمثل إما فئات Classes, أو واجهات Interfaces, أو تراقيم Enumerations.


كود VB
كود :
Imports System
Imports System.Reflection
Namespace ReflectionDemo
    Class ReflectedTypes
        Private Shared Sub Main(ByVal args As String())
            Dim LoadedAssembly As Assembly = Assembly.Load("mscorlib.dll")
            Dim ExistingTypes As System.Type() = LoadedAssembly.GetTypes()
            For Each type As Type In ExistingTypes
                Console.WriteLine(type.ToString())
            Next
            Console.WriteLine(ExistingTypes.Length & " Types Discovered in mscorlib.dll")
            Console.ReadLine()
        End Sub
    End Class
End Namespace


كود C#
كود :
using System;
using System.Reflection ;
namespace ReflectionDemoCSharp
{
    class ReflectedTypes
    {
        [STAThread]
        static void Main(string[] args)
        {
            Assembly LoadedAssembly = Assembly.Load ("mscorlib.dll");
            System.Type[] ExistingTypes = LoadedAssembly.GetTypes ();
            foreach(Type type in ExistingTypes)
                Console.WriteLine (type.ToString ());
            Console.WriteLine (ExistingTypes.Length +
               " Types Discovered in mscorlib.dll");
            Console.ReadLine ();
        }
   }
}


سيقوم الـ Console بعرض جميع الأنواع الموجودة ضمن التجميع mscorlib.dll, وهذا مجرد مقطع من الناتج:


كود :
System.Object
System.ICloneable
System.Collections.IEnumerable
System.Collections.ICollection
System.Collections.IList
System.Array
System.Array+SorterObjectArray
System.Array+SorterGenericArray
System.Collections.IEnumerator
1480 Types Discovered in mscorlib.dll


تطبيق Reflection على نوع محدّد


في المثال التالي, سنقوم بعملية انعكاس على نوع واحد والكشف عن الأعضاء الخاصة به, الإجراء Type.GetType تأخذ معامل واحد من النوع string, وتعيد كائن من النوع الموافق, وللاستعلام عن أعضاء نوع معين نستخدم الإجراء Type.GetMembers والتي تعيد مصفوفة من النوع MemberInfo


كود VB:


كود :
Imports System
Imports System.Reflection
Namespace ReflectionDemo
    Class ReflectedTypes
        Sub Main(ByVal args As String())
            Dim TypeToReflect As Type = Type.GetType("System.Int32")
            Dim Members As System.Reflection.MemberInfo() = TypeToReflect.GetMembers()
            
            Console.WriteLine("Members of " & TypeToReflect.ToString())
            Console.WriteLine()
            For Each member As MemberInfo In Members
                Console.WriteLine(member)
            Next
            Console.ReadLine()
        End Sub
    End Class
End Namespace


كود C#
كود :
using System;
using System.Reflection ;
namespace ReflectionDemoCSharp
{
    class ReflectedTypes
    {
        [STAThread]
        static void Main(string[] args)
        {
            Type TypeToReflect = Type.GetType("System.Int32");
            System.Reflection.MemberInfo[] Members =TypeToReflect.GetMembers();
            Console.WriteLine ("Members of "+TypeToReflect.ToString ());
            Console.WriteLine();
            foreach (MemberInfo member in Members )
                Console.WriteLine(member);
            Console.ReadLine ();
        }
    }
}


الناتج سيكون كالتالي:


كود :
Members of System.Int32
Int32 MaxValue
Int32 MinValue
System.String ToString(System.IFormatProvider)
System.TypeCode GetTypeCode()
System.String ToString(System.String, System.IFormatProvider)
Int32 CompareTo(System.Object)
Int32 GetHashCode()
Boolean Equals(System.Object)
System.String ToString()
System.String ToString(System.String)
Int32 Parse(System.String)
Int32 Parse(System.String, System.Globalization.NumberStyles)
Int32 Parse(System.String, System.IFormatProvider)
Int32 Parse(System.String, System.Globalization.NumberStyles, System.IFormatProvider)
System.Type GetType()


الحصول على الأعضاء حسب أنواعها:


كود :
Dim Members As System.Reflection.MemberInfo() = TypetoReflect.GetMembers()
إرجاع كافة الأعضاء الخاصة بالنوع الذي نستعلم عنه.
كود :
Dim Members As System.Reflection.MethodInfo() = TypetoReflect.GetMethods()


إرجاع الإجراءات الخاصة بالنوع الذي نستعلم عنه.


كود :
Dim Members As System.Reflection.FieldInfo() = TypetoReflect.GetFields()
إرجاع الحقول الخاصة بالنوع الذي نستعلم عنه.


كود :
Dim Members As System.Reflection.PropertiesInfo() = TypetoReflect.GetProperties()
إرجاع الخصائص الخاصة بالنوع الذي نستعلم عنه.


كود :
Dim Members As System.Reflection.EventInfo() = TypetoReflect.GetEvents()
إرجاع الأحداث الخاصة بالنوع الذي نستعلم عنه.


كود :
Dim Members As System.Reflection.ConstructorInfo() = TypetoReflect.GetConstructors()
إرجاع المنشئات الخاصة بالنوع الذي نستعلم عنه.


كود :
Dim Members As System.Type () = TypetoReflect.GetInterfaces()
إرجاع الواجهات التي ينفذها النوع الذي نستعلم عنه.
الرد }}}
تم الشكر بواسطة: ابو ابراهيم , ابو ليلى
#3
الاستدعاء الديناميكي باستخدام Type.InvokeMember


المثال التالي يوضح كيفية استدعاء إجراء ما بشكل ديناميكي باستخدام الإجراء Type.InvokeMember
سنقوم باستدعاء الإجراء Equals الخاص بالفئة System.String والذي يقوم بمقارنة سلسلتين نصيتين, حيث يقوم تمرير البرنامج التالي تمرير المعاملين النصيّين. يقوم الإجراء Type.InvokeMember باستدعاء إجراء ما من خلال اسمه.
معاملات الإجراء Type.InvokeMember كالتالي:
  • المعامل الأول من النوع String, والذي يمثل اسم الإجراء الذي نرغب في استدعائه.
  • المعامل الثاني من نوع ترقيم BindingFlags enumeration والذي يحدد كيفية الربط, وتتحكم في كيفية الوصول إلى الأعضاء Members
  • المعامل الثالث من النوع Binder والذي يعرّف مجموعة من الخصائص ويقوم بتمكين الربط, يمكن ان يكون هذا الكائن Null أو Nothing , يعطي هذا المعامل خيارات تتحكم في كيفية تحديد الإجراءات المتجاوزة Overloaded Methods, ويحدد كذلك بكيفية تمرير المعاملات وتحويلها.
  • المعامل الرابع كائن من النوع Object والذي سيتم تمرير ناتج الإجراء المستدعى.
  • المعامل الخامس مصفوفة من النوع Object والتي تمثل المعاملات للإجراء الذي نستدعيه.
  • سيتضح كا شيء أكثر في المثال التالي:

كود VB:


كود :
Imports System
Imports System.Reflection
Namespace ReflectionDemoCSharp
    Class ReflectedTypes
        Private Shared Sub Main(ByVal args As String())
            Dim TypeToReflect As Type = Type.[GetType]("System.String")
            Dim result As Object = Nothing
            Dim arguments As Object() = {"abc", "xyz"}
            result = TypeToReflect.InvokeMember("Equals", BindingFlags.InvokeMethod, Nothing, result, arguments)
            Console.WriteLine(result.ToString())
            Console.ReadLine()
        End Sub
    End Class
End Namespace


كود C#
كود :
using System;
using System.Reflection ;
namespace ReflectionDemoCSharp
{
    class ReflectedTypes
    {
        [STAThread]
        static void Main(string[] args)
        {
            Type TypeToReflect = Type.GetType("System.String");
            object result = null;
            object[] arguments = {"abc","xyz"};
            result = TypeToReflect.InvokeMember ("Equals",
              BindingFlags.InvokeMethod, null, result, arguments);
            Console.WriteLine (result.ToString ());
            Console.ReadLine ();
        }
    }
}


الناتج في هذه الحالة false.
الرد }}}
تم الشكر بواسطة: ابو ابراهيم , ابو ليلى
#4
Reflection.Emit – - إنشاء الأنواع ديناميكيا وقت التشغيل واستدعاء أعضائها.


يمكِّن Reflection.Emit من إنشاء الأنواع الجديدة ديناميكيا وقت التشغيل بإمكانك إنشاء التجميعات وتعريف الوحدات Modules, والأنواع , والإجراءات والخصائص...التي ترغب بإضافتها إليها, يمكن تشغيل تلك التجميعات تلقائيا أو يمكنك حفظها إلى القرص, يتم استدعاء اعضاء الأنواع المعرفة أثناء وقت التشغيل دائما باستخدام الإجراء Type.InvokeMember.
يمكِّن Reflection.Emit أيضا المترجمات Compilers من أرسال بيانات التعريف MetaData, وبيانات لغة Microsoft الوسيطة MSIL أثناء التشغيل.


أريد أن أضيف أيضا أن لتقنية CodeDom علاقة بالموضوع ولو أجرينا مقارنة بين التقنيتين سيتضح ذلك ما يلي:


محاسن استخدام Reflection.Emit


  • يمكن إنشاء تجميعات ديناميكية والعمل عليها بشكل مستقل, مما يمكِّن من تقليل حجم الذاكرة المستخدمة.
  • يمكن توليد فئات حقيقية وإنشاء اعضاء داخلية (الاعضاء الديناميكية)
  • إمكانيات الكود الناتج مستقل عن اللغة التي تكتب بها, لأنه يعتمد في الأساس على توليد تعليمات IL.
  • أسرع وأحسن بكثير من ناحية الأداء.



مساوئ استخدامها:


  • ليست قابلة للتنقيح Debugging, لذلك من الصعب اكتشاف الأخطاء بها.
  • احتمال وجود أخطاء في الفئات الديناميكية كبير.



محاسن استخدام CodeDom
  • سهل التعامل والاستخدام
  • الكود الذي يتم توليده قابل للتنقيح Debugging
  • يمكن اكتشاف الأخطاء وإصلاحها بسهولة



مساوئ استخدام CodeDom


  • لايمكن إنشاء فئات جديدة في أي وقت, وبشكل مستقل.
  • إمكانيات الكود الناتج مرتبط بإمكانيات اللغة التي تكتب بها الكود.
  • أبطئ في الأداء من Reflection.Emit



للمزيد من المعلومات حول CodeDom, راجع مقال الاستاذ BADRMEDIA: معلومة ::: أجعل المستخدم عبر تطبيقك يخرج برامج أخري - CodeDom


سنقوم في المثال التالي بإنشاء فئة DoMath وتعريف إجراء DoSum بداخل التجميع المسمى Math أول ما يجب علينا القيام به, هو تعريف كائن من النوع AssemblyName وإعطائه اسما ما.


كود VB


كود :
Dim assemblyName As New AssemblyName()
assemblyName.Name = "Math"


كود C#


كود :
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "Math";


بعد ذلك سنستخدم الفئة AssemblyBuilder لتعريف تجميع ديناميكي في المجال الحالي للتطبيق AppDomain.


يجب علينا تمرير معاملين الأول هو كائن AssemblyName المعرّف سابقاً والثاني ترقيم من النوع AssemblyBuilderAccess وهو يأخذ أحد القيم الثلاث إما Run, RunAndSave, أو Save, والذي يحدد إن كان سيتم تشغيل التجميع فقط, أو حفظه إلى القرص.


كود VB


كود :
Dim CreatedAssembly As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave)


كود C#


كود :
AssemblyBuilder CreatedAssembly =
AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,  AssemblyBuilderAccess.RunAndSave);


والآن لإنشاء Module داخل التجميع السابق, سنقوم بتنفيذ احد أعضاء الفئة AssemblyBuilder وهو DefineDynamicModule والذي يعيد كائنا من النوع ModuleBuilder, يجب تمرير معاملين للإجراء السابق, اسم Module, واسم الملف الذي سيحفظ به.


كود VB


كود :
Dim AssemblyModule As ModuleBuilder = CreatedAssembly.DefineDynamicModule("MathModule", "Math.dll")


كود C#


كود :
ModuleBuilder AssemblyModule =
CreatedAssembly.DefineDynamicModule("MathModule","Math.dll");


الخطوة التالية هي إنشاء فئة داخل ال Module الذي انشاناه للتو, وسنسميها DoMath.
للقيام بذلك سنستخدم الفئة TypeBuilder لتعريف الفئة الجديدة سنستدعي الإجراء AssemblyModule.DefineType والتي تعيد كائن من النوع TypeBuilder


كود VB


كود :
Dim MathType As TypeBuilder = AssemblyModule.DefineType("DoMath", TypeAttributes. Or TypeAttributes.)
كود C#


كود :
TypeBuilder MathType = AssemblyModule.DefineType("DoMath",
       TypeAttributes.Public | TypeAttributes.Class);


بعد ذلك سنقوم بكتابة الإجراء Sum للقيام بجمع عددين وإرجاع الناتج, للقيام بذلك سنستعين بالفئة MethodBuilder التي تحتوي على إجراء DefineMethod’ يأخذ هذا الإجراء القيم التالية: اسم الإجراء (String), سمات الإجراء الجديد MethodAttributes Enum, نوع القيمة العائدة, مصفوفة أنواع الممررات Parameters.
كود VB


كود :
Dim ParamTypes As System.Type() = New Type() {GetType(Integer), GetType(Integer)}
Dim SumMethod As MethodBuilder = MathType.DefineMethod("Sum", MethodAttributes.Public, GetType(Integer), ParamTypes)


كود C#


كود :
System.Type [] ParamTypes = new Type[] { typeof(int),typeof(int) };
MethodBuilder SumMethod = MathType.DefineMethod("Sum",
              MethodAttributes.Public, typeof(int), ParamTypes);


العملية السابقة غير كافية, يجب تعريف ممررين جديدين باستخدام الإجراء DefineParameter للفئة MethodBuilder, الكائن العائدة من هذا الإجراء هو من النوع ParameterBuilder , نمرر لهذا الإجراء فهرس الممرر Parameter Index, وقيمة الترقيم ParameterAttribute, ثم اسم الممرر.


كود VB


كود :
Dim Param1 As ParameterBuilder = SumMethod.DefineParameter(1, ParameterAttributes.In, "num1")
Dim Param2 As ParameterBuilder = SumMethod.DefineParameter(2, ParameterAttributes.In, "num2")


كود C#
كود :
ParameterBuilder Param1 =
    SumMethod.DefineParameter(1,ParameterAttributes.In ,"num1");
ParameterBuilder Param2 =
    SumMethod.DefineParameter(2,ParameterAttributes.In ,"num2");


الخطوة القادمة هي الأهم, وهي كتابة تعليمات MSIL عن طريق الكود, نخيل وكأن برنامجك عبارة عن مترجم Compiler, سنستخدم لذلك الفئة ILGenerator العائدة من الإجراء MethodBuilder.GetILGenerator:


كود VB


كود :
Dim ilGenerator As ILGenerator = SumMethod.GetILGenerator()
كود C#


كود :
ILGenerator ilGenerator = SumMethod.GetILGenerator();
تقوم الفئة ILGenerator بإرسال Opcodes MSIL تماما كما يقوم مترجم Visual Basic, الفئة Opcodes تحتوي على حقول Fields كل حقل يعبر عن تعليمة من تعليمات MSIL, في الكود التالي سنقوم بتمرير Arguments الخاصة بالإجراء Sum بحيث ستقوم الفئة ILGenerator اولاُ بوضع الممررات في الرصة Stack, ثم بعد ذلك تقوم بتنفيذ التعليمة المناسبة إلى الرصة (في مثالنا هذا سنمرر التعليمة Add التي تمثل عملية الجمع), التعليمة التالية التي ستدخل الرصة هي التعليمة Ret والتي تقوم بإرجاع ناتج التعليمة Add, الكود التالي سيوضح لك:


كود VB


كود :
ilGenerator.Emit(OpCodes.Ldarg_1)  
ilGenerator.Emit(OpCodes.Ldarg_2)
ilGenerator.Emit(OpCodes.Add)
ilGenerator.Emit(OpCodes.Ret)


كود C#


كود :
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit (OpCodes.Ldarg_2);
ilGenerator.Emit (OpCodes.Add );
ilGenerator.Emit(OpCodes.Ret);


الخطوة التالية, هي إنهاء عملية كتابة الفئة الجديدة DoMath وإرجاع التجميع الجديد Math
كود VB


كود :
MathType.CreateType()
Return CreatedAssembly


كود C#


كود :
MathType.CreateType();
return CreatedAssembly;


يمكن بسهولة حفظ التجميع الجديد على القرص


كود :
CreatedAssembly.Save("Math.dll")


لاستخدام التجميع الذي أنشاناه ديناميكيا أثناء وقت التشغيل, يجب استخدام الفئة Activator
لاحظ انه من الصعب التعرف تلقائيا على الانواع الجديدة التي انشاناها سابقا لذلك الحل الوحيد لاستدعاء تلك الأنواع هو استخدام Reflection مجددا على التجميع الجديد ثم استخدام الإجراء InvokeMemeber لتنفيذ الإجراء الجديد Sum الخاصة بالفئة الجديدة DoMath


كود VB
كود :
Dim Parameters As Object() = New Object(1) {}
Parameters(0) = DirectCast((5), Object)
Parameters(1) = DirectCast((9), Object)
Dim EmitObj As Object = Activator.CreateInstance(MathType, False)
Dim Result As Object = MathType.InvokeMember("Sum", BindingFlags.InvokeMethod, Nothing, EmitObj, Parameters)
Console.WriteLine("Sum of {0}+{1} is {2}", Parameters(0), Parameters(1), Result.ToString())


كود C#
كود :
object[] Parameters = new object [2];
Parameters[0] =  (object) (5);
Parameters[1] =  (object) (9);
object EmitObj = Activator.CreateInstance(MathType,false);
object Result = MathType.InvokeMember("Sum",
     BindingFlags.InvokeMethod ,null,EmitObj,Parameters);
Console.WriteLine ("Sum of {0}+{1} is {2}",
   Parameters[0],Parameters[1],Result.ToString ());


انتهى الموضوع, لتحميل المثال اضغظ هنا


المراجع المعتمدة:


MSDN
The Code Project
WikiPedia
الرد }}}
تم الشكر بواسطة: Fantastico , ابو ابراهيم , ابو ليلى
#5
بارك الله فيك أخي موضوع غاية في الروعة Smile
تم التقييم :d
الرد }}}
تم الشكر بواسطة:
#6
أقدم لك جزيل الشكر أخي على هذا الموضوع الثمين

لدي سؤال : هل من طريقة أخرى أسهل لكتابة الشيفرات داخل الإجراء غير الطريقة ilGenerator.Emit

ثانيا اذا كان في متناولك بعض المواضيع المكملة او الكتب العربية التي تتحدث عن المجمعات وفئات الانعكاس فلك جزيل الشكر لو تفضلت علي بها.
انا مهتم بمعرفة طريقة تحويل النص الى Method
الرد }}}
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  شاهد حداءة ( مقال الوحي يضحد كل قول وإن قال العظام العالمون ) مسوق اونلاين 0 362 23-08-22, 10:33 PM
آخر رد: مسوق اونلاين
  الفرق بين الحلم والكابوس وكيفية التفرقة بينهم حسام هيكل 0 932 17-04-20, 12:35 AM
آخر رد: حسام هيكل
  [مقال منقول] مشروع Mono : شغل الدوت نت على اللينكس أو أي نظام تشغيل تحلم به الشاكي لله 6 5,448 13-03-14, 02:02 AM
آخر رد: الشاكي لله
  مقال- كيف نحل مشاكلنا بأنفسنا- RaggiTech 0 2,181 27-10-12, 04:23 PM
آخر رد: RaggiTech
  مقال تقني- Windows Vista وVisual Studio RaggiTech 0 2,298 09-10-12, 11:46 AM
آخر رد: RaggiTech
  مقال: DotNET Components Licencing RaggiTech 0 1,837 09-10-12, 11:44 AM
آخر رد: RaggiTech
  مقال- التخزين المعزول Isolated Storage RaggiTech 1 2,035 09-10-12, 11:42 AM
آخر رد: RaggiTech
  مقال- التوثيق في الدوت نت Documenting In .NET RaggiTech 4 3,214 09-10-12, 11:40 AM
آخر رد: RaggiTech
  مقال: كيف نحل مشاكلنا بأنفسنا- RaggiTech 0 2,005 09-10-12, 11:25 AM
آخر رد: RaggiTech
  مقال- ما لا تعرفونه عن Web browser Control RaggiTech 1 2,065 09-10-12, 11:23 AM
آخر رد: RaggiTech

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


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