ج# التحويلات الضمنية
-
03-10-2019 - |
سؤال
أنا أعمل حاليًا على تطبيق حيث أحتاج إلى تحميل البيانات من قاعدة بيانات SQL ثم تعيين القيم التي تم استردادها في خصائص كائن ما. أقوم بذلك باستخدام التفكير لأن أسماء الخصائص وأسماء الأعمدة هي نفسها. ومع ذلك ، فإن العديد من الخصائص تستخدم نوع بنية مخصصة يمثل في الأساس غلاف العملة للنوع العشري. لقد حددت تحويلًا ضمنيًا في بنيتي:
public static implicit operator Currency(decimal d)
{
return new Currency(d);
}
هذا يعمل بشكل جيد عندما أستخدمه في الكود. ومع ذلك ، عندما يكون لدي هذا:
foreach (PropertyInfo p in props)
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
إنه يلقي enbumentException يفيد أنه لا يمكن تحويله من النظام. أنا مرتبك لأنه يعمل بشكل جيد في أي ظرف آخر.
المحلول
أنا فكر في تحتاج إلى إلغاء توصيل القيمة أولاً في table.Rows[0][p.Name]
ك decimal
.
بعبارات أخرى:
foreach (PropertyInfo p in props)
{
if (p.PropertyType == typeof(Currency))
{
Currency c = (decimal)table.Rows[0][p.Name];
p.SetValue(this, c, null);
}
else
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
}
هذه مشكلة رأيتها مرة أو مرتين من قبل ، لذلك قررت بالفعل ذلك اكتب مدونة منشور حول هذا الموضوع. أي شخص يبحث عن المزيد من التفسير ، لا تتردد في إعطائها قراءة.
نصائح أخرى
لسوء الحظ ، لا يتم استخدام مشغلي التحويل المعرفة من قبل المستخدم بواسطة وقت التشغيل ؛ يتم استخدامها فقط من قبل المترجم في وقت الترجمة. لذلك إذا كنت تأخذ بقوة decimal
وتعيينه إلى طائرة قوية Currency
, ، سيقوم المترجم بإدخال مكالمة إلى مشغل التحويل الخاص بك والجميع سعداء. ومع ذلك ، عندما تتصل SetValue
كما تفعل هنا ، يتوقع منك وقت التشغيل أن تمنحه قيمة من النوع المناسب ؛ ليس لدى وقت التشغيل أي فكرة عن وجود مشغل التحويل هذا ، ولن يسميه أبدًا.
أفترض ذلك table
من النوع DataTable
في الكود الخاص بك ، لذلك يقوم المفهرس الأول بإرجاع أ DataRow
, والثاني يعيد object
. ثم PropertyInfo.SetValue
يأخذ أيضا object
كحجة ثانية. في أي مكان في هذا الرمز يحدث الممثلين في الكود, ، وهذا هو السبب في عدم تطبيق مشغل التحويل الزائد.
بشكل عام ، يتم تطبيقه فقط عندما تكون أنواع ثابتة معروفة (نسيان dynamic
في C# 4.0 للحظة). لا يتم تطبيقه عند الملاكمة والملاكمة. في هذه الحالة ، فارس على DataRow
صناديق القيمة ، و PropertyInfo.SetValue
يحاول إلغاء الازدهار إلى نوع مختلف - ويفشل.
على الرغم من أنني لا أجيب على مشكلتك ، أعتقد في هذا النوع من الموقف ، سيكون من الأفضل استخدام إطار عمل ORM مثل إطار الكيان أو nhibernate الذي سيقوم بتخطيط جداولك في كائنات المجال الخاصة بك والتعامل مع جميع التحويلات لك. يعد استخدام شيء مثل الانعكاس لمعرفة الحقول لملء كائن المجال طريقة بطيئة للقيام بذلك.