هل احتجت في يوم أو في مهمة إلى تغير نوع كائن object إلى كائن غير معرف (anonymous type)؟ الأمر في غاية البساطة:
private T ConvertTo<T>(T typeHolder, object obj) => (T)obj;
|
ولكن قد تتساءل ما الحاجة لهذه المعلية وخاصة أن شرط التحويل أن يكون الكائن object هو فعلا يمثل كائن غير معرف حتى يتم التحويل بشكل ناجح وصحيح.
تساؤلك في محله والجواب انه قد تحتاج إلى إنشاء نسخة ثانية أو ثالثة من كائن غير معرف (anonoymous type) باستخدام
FormatterServices أو Activator.
ملاحظة: هناك فرق في قدارت كلا الفئتين Activatior و FormatterServices. في حين أن Activator تتطلب منك مسبقا معرفة شكل الباني من حيث القيم الممررة (برامترات) إذ أن الأنواع غير مسبقة التعريف لا تحتوي على باني افتراضي أو باني بدون قيم ممررة (Parameterless Constructor) وهذا سوف يسبب متاعب خاصة مع الأنواع المعقدة (Complex Type)
var car = new { Maker = “BMW”, Type = “Sedan”, Year = 2017 };
var anotherCar = Activator.CreateInstance(car.GetType(), new object[] { “Mercedes-Benz”, “Four-Wheels”, 1995 });
anotherCar.Dump();
|
5ø4
|
|
Maker
|
Mercedes-Benz
|
Type
|
Four-Wheels
|
Year
|
1995
|
ولكن ماذا عن المثال التالي:
var complexCar = new { Maker = “BMW”, Owners = new { First = “Ahmad”, Second = “Yaser” } };
var anotherComplexCar = Activator.CreateInstance(complexCar.GetType(), new object[] { “Mercedes”, new object[] { “Lama”, “Malek” } });
anotherComplexCar.Dump();
|
6MissingMethodException4
|
Constructor on type ‘<>f__AnonymousType1`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[<>f__Anonymou…
|
المشكلة أن القيم الممررة لم تكن توافق شكل الباني
الحل الثاني هو استخدام FormatterService التي توفر عدد من التوابع لإنشاء نسخة من كائن object الميزة التي تقدمها أنها ستقوم بإنشاء نسخة من كائن دون استدعاء الباني
var complexCar = new { Maker = “BMW”, Owners = new { First = “Ahmad”, Second = “Yaser” } };
//var anotherComplexCar = Activator.CreateInstance(complexCar.GetType(), new object[] {“Mercedes”, new object[] { “Lama”, “Malek”}} );
var anotherComplexCar = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(complexCar.GetType());
anotherComplexCar.Dump();
|
5ø4
|
|
Maker
|
null
|
Owners
|
null
|
لكن التابع GetUninitializedObject سوف يعيد نسخة لكن من نوع object وبالتالي نحتاج إلى عمل تغير نوع من object إلى نوع الكائن المجهول. علينا استخدام التابع المعرف في أول المقالة على النحو التالي:
private T CastTo<T>(T typeHolder, object obj) => (T)obj;
var complexCar = new { Maker = “BMW”, Owners = new { First = “Ahmad”, Second = “Yaser” } };
//var anotherComplexCar = Activator.CreateInstance(complexCar.GetType(), new object[] {“Mercedes”, new object[] { “Lama”, “Malek”}} );
var anotherComplexCar = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(complexCar.GetType());
var castedAnotherComplexCar = CastTo(complexCar, anotherComplexCar);
anotherComplexCar.Dump();
|
المصادر:
[1]. https://stackoverflow.com/a/1409776/2696230
[2]. https://connect.microsoft.com/VisualStudio/feedback/details/521722/system-activator-createinstance-throws-system-missingmethodexception-with-constructor-containing-an-optional-parameter
[3]. https://stackoverflow.com/a/2501231/2696230
هل احتجت في يوم أو في مهمة إلى تغير نوع كائن object إلى كائن غير معرف (anonymous type)؟ الأمر في غاية البساطة:
private T ConvertTo<T>(T typeHolder, object obj) => (T)obj;
|
ولكن قد تتساءل ما الحاجة لهذه المعلية وخاصة أن شرط التحويل أن يكون الكائن object هو فعلا يمثل كائن غير معرف حتى يتم التحويل بشكل ناجح وصحيح.
تساؤلك في محله والجواب انه قد تحتاج إلى إنشاء نسخة ثانية أو ثالثة من كائن غير معرف (anonoymous type) باستخدام
FormatterServices أو Activator.
ملاحظة: هناك فرق في قدارت كلا الفئتين Activatior و FormatterServices. في حين أن Activator تتطلب منك مسبقا معرفة شكل الباني من حيث القيم الممررة (برامترات) إذ أن الأنواع غير مسبقة التعريف لا تحتوي على باني افتراضي أو باني بدون قيم ممررة (Parameterless Constructor) وهذا سوف يسبب متاعب خاصة مع الأنواع المعقدة (Complex Type)
var car = new { Maker = “BMW”, Type = “Sedan”, Year = 2017 }; var anotherCar = Activator.CreateInstance(car.GetType(), new object[] { “Mercedes-Benz”, “Four-Wheels”, 1995 }); anotherCar.Dump();
|
5ø4
|
|
Maker
|
Mercedes-Benz
|
Type
|
Four-Wheels
|
Year
|
1995
|
ولكن ماذا عن المثال التالي:
var complexCar = new { Maker = “BMW”, Owners = new { First = “Ahmad”, Second = “Yaser” } }; var anotherComplexCar = Activator.CreateInstance(complexCar.GetType(), new object[] { “Mercedes”, new object[] { “Lama”, “Malek” } }); anotherComplexCar.Dump();
|
6MissingMethodException4
|
Constructor on type ‘<>f__AnonymousType1`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[<>f__Anonymou…
|
المشكلة أن القيم الممررة لم تكن توافق شكل الباني
الحل الثاني هو استخدام FormatterService التي توفر عدد من التوابع لإنشاء نسخة من كائن object الميزة التي تقدمها أنها ستقوم بإنشاء نسخة من كائن دون استدعاء الباني
var complexCar = new { Maker = “BMW”, Owners = new { First = “Ahmad”, Second = “Yaser” } }; //var anotherComplexCar = Activator.CreateInstance(complexCar.GetType(), new object[] {“Mercedes”, new object[] { “Lama”, “Malek”}} ); var anotherComplexCar = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(complexCar.GetType()); anotherComplexCar.Dump();
|
5ø4
|
|
Maker
|
null
|
Owners
|
null
|
لكن التابع GetUninitializedObject سوف يعيد نسخة لكن من نوع object وبالتالي نحتاج إلى عمل تغير نوع من object إلى نوع الكائن المجهول. علينا استخدام التابع المعرف في أول المقالة على النحو التالي:
private T CastTo<T>(T typeHolder, object obj) => (T)obj;
var complexCar = new { Maker = “BMW”, Owners = new { First = “Ahmad”, Second = “Yaser” } }; //var anotherComplexCar = Activator.CreateInstance(complexCar.GetType(), new object[] {“Mercedes”, new object[] { “Lama”, “Malek”}} ); var anotherComplexCar = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(complexCar.GetType()); var castedAnotherComplexCar = CastTo(complexCar, anotherComplexCar); anotherComplexCar.Dump();
|
المصادر:
[1]. https://stackoverflow.com/a/1409776/2696230
[2]. https://connect.microsoft.com/VisualStudio/feedback/details/521722/system-activator-createinstance-throws-system-missingmethodexception-with-constructor-containing-an-optional-parameter
[3]. https://stackoverflow.com/a/2501231/2696230