سؤال

أرغب في تعيين خاصية كائن من خلال انعكاس، مع قيمة النوع stringوبعد لذلك، على سبيل المثال، افترض أن لدي Ship فئة، مع خاصية Latitude, ، وهو double.

إليك ما أود القيام به:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, value, null);

كما هو، وهذا يلقي ArgumentException:

كائن من النوع "System.String" لا يمكن تحويله إلى كتابة "System.Duble".

كيف يمكنني تحويل القيمة إلى النوع المناسب، بناء على propertyInfo?

هل كانت مفيدة؟

المحلول

يمكنك استخدام Convert.ChangeType() - يسمح لك باستخدام معلومات وقت التشغيل عن أي IConvertible اكتب لتغيير تنسيقات التمثيل. ليست كل التحويلات ممكنة، ولكن قد تحتاج إلى كتابة منطق حالة خاصة إذا كنت ترغب في دعم التحويلات من أنواع ليست كذلك IConvertible.

سيكون الكود المقابل (دون معالجة استثناء أو منطق حالة خاصة):

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

نصائح أخرى

كما قال العديد من الآخرين، تريد استخدامها Convert.ChangeType:

propertyInfo.SetValue(ship,
    Convert.ChangeType(value, propertyInfo.PropertyType),
    null);

في الواقع، أنصحك بإلقاء نظرة على كامل Convert فصل.

هذه الفئة، والعديد من الفئات المفيدة الأخرى هي جزء من System مساحة الاسم. وبعد أجد أنه من المفيد مسح مساحة الاسم هذه كل عام أو نحو ذلك لمعرفة الميزات التي اشتقتها. جربها!

لاحظت الكثير من الناس يوصون Convert.ChangeType - هذا يعمل في بعض الحالات ولكن بمجرد أن تبدأ في إشراك nullable أنواع سوف تبدأ في تلقي InvalidCastExceptions:

http:/ weblogs.asp.net/pjohnson/archive/2006/02/07/convert.changeType-doesn_2700_t-handle-spx.

تمت كتابة غلاف قبل بضع سنوات للتعامل مع هذا ولكن هذا ليس مثاليا أيضا.

http:/ weblogs.asp.net/pjohnson/archive/2006/02/07/convert.changeType-doesn_2700_t-handle-spx.

يمكنك استخدام محول النوع (أي فحص خطأ):

Ship ship = new Ship();
string value = "5.5";
var property = ship.GetType().GetProperty("Latitude");
var convertedValue = property.Converter.ConvertFrom(value);
property.SetValue(self, convertedValue);

من حيث تنظيم التعليمات البرمجية، يمكنك إنشاء نوع من mixin ذلك من شأنه أن يؤدي إلى رمز مثل هذا:

Ship ship = new Ship();
ship.SetPropertyAsString("Latitude", "5.5");

سيتم تحقيق ذلك مع هذا الرمز:

public interface MPropertyAsStringSettable { }
public static class PropertyAsStringSettable {
  public static void SetPropertyAsString(
    this MPropertyAsStringSettable self, string propertyName, string value) {
    var property = TypeDescriptor.GetProperties(self)[propertyName];
    var convertedValue = property.Converter.ConvertFrom(value);
    property.SetValue(self, convertedValue);
  }
}

public class Ship : MPropertyAsStringSettable {
  public double Latitude { get; set; }
  // ...
}

MPropertyAsStringSettable يمكن إعادة استخدامها للعديد من الفصول المختلفة.

يمكنك أيضا إنشاء العرف الخاص بك محولات نوع لإرفاق خصائصك أو الفئات:

public class Ship : MPropertyAsStringSettable {
  public Latitude Latitude { get; set; }
  // ...
}

[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }

حاولت الجواب من lbushkin. وقد عملت كبيرة، لكنها لن تعمل من أجل قيم فارغة وحقول حقل. لذلك لقد غيرت ذلك إلى هذا:

propertyName= "Latitude";
PropertyInfo propertyInfo = ship.GetType().GetProperty(propertyName);
if (propertyInfo != null)
{
     Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
     object safeValue = (value == null) ? null : Convert.ChangeType(value, t);
     propertyInfo.SetValue(ship, safeValue, null);
}

ربما كنت تبحث عن Convert.ChangeType طريقة. علي سبيل المثال:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

استخدام Convert.ChangeType والحصول على النوع لتحويل من PropertyInfo.PropertyType.

propertyInfo.SetValue( ship,
                       Convert.ChangeType( value, propertyInfo.PropertyType ),
                       null );

سأجيب على هذا مع إجابة عامة. عادة هذه الإجابات لا تعمل مع GUIDs. هنا نسخة عمل مع GUID أيضا.

var stringVal="6e3ba183-89d9-e611-80c2-00155dcfb231"; // guid value as string to set
var prop = obj.GetType().GetProperty("FooGuidProperty"); // property to be setted
var propType = prop.PropertyType;

// var will be type of guid here
var valWithRealType = TypeDescriptor.GetConverter(propType).ConvertFrom(stringVal); 

أو يمكنك محاولة:

propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

//But this will cause problems if your string value IsNullOrEmplty...

إذا كنت تكتب تطبيق مترو، يجب عليك استخدام رمز آخر:

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType));

ملحوظة:

ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");

بدلا من

ship.GetType().GetProperty("Latitude");

عند استخدام التعليمات البرمجية التالية يجب أن يحل مشكلتك:

item.SetProperty(prop.Name, Convert.ChangeType(item.GetProperty(prop.Name).ToString().Trim(), prop.PropertyType));

هل تتطلع للعب حولك مع انعكاس أم أنك تبحث عن بناء قطعة إنتاج من البرامج؟ أود أن أسأل لماذا تستخدم الانعكاس لتعيين خاصية.

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top