Monthly Archives: سبتمبر 2017

كيف تغير نوع كائن من إلى كائن مجهول (بدون التعريف)

هل احتجت في يوم أو في مهمة إلى تغير نوع كائن 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

هل احتجت في يوم أو في مهمة إلى تغير نوع كائن 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