एक स्ट्रिंग मान के साथ प्रतिबिंब द्वारा एक संपत्ति निर्धारित करना


312

मैं प्रकार के मूल्य के साथ, प्रतिबिंब के माध्यम से किसी वस्तु की एक संपत्ति निर्धारित करना चाहता हूं string । इसलिए, उदाहरण के लिए, मान लीजिए कि मेरे पास Shipएक संपत्ति है Latitude, जो एक संपत्ति है double

यहाँ मैं क्या करना चाहता हूँ:

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

जैसा है, यह फेंकता है a ArgumentException :

प्रकार के सिस्टम 'System.String' को 'System.Double' प्रकार में परिवर्तित नहीं किया जा सकता है।

मैं मूल्य को किस प्रकार, उचित प्रकार पर आधारित कर सकता हूं propertyInfo?


1
आपके लिए प्रश्न: क्या यह कस्टम ORM समाधान का हिस्सा है?
user3308043

जवाबों:


527

आप उपयोग कर सकते हैं 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);

नीचे @AliKaraca उत्तर की समीक्षा करें। यह और नीचे वाला दोनों तेज और ढीले हैं लेकिन सामान्य प्रकार के लिए काम करते हैं।
आरोन हडोन

वहाँ एक है TryChangeTypeया CanChangeType?
शमी वेइटहैंडलर

34

जैसा कि कई अन्य लोगों ने कहा है, आप उपयोग करना चाहते हैं Convert.ChangeType:

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

वास्तव में, मैं आपको संपूर्ण Convertकक्षा को देखने की सलाह देता हूं ।

यह वर्ग, और कई अन्य उपयोगी वर्ग Systemनेमस्पेस का हिस्सा हैं । मुझे हर साल उस नाम स्थान को स्कैन करने के लिए उपयोगी लगता है और यह देखने के लिए कि मैंने क्या सुविधाएँ देखी हैं। कोशिश करो!


1
ओपी संभवतः किसी भी प्रकार की एक संपत्ति निर्धारित करने के लिए सामान्य उत्तर चाहता है, जिसमें एक स्ट्रिंग से एक स्पष्ट रूपांतरण होता है।
डैनियल इयरविकर

अच्छी बात। मैं वास्तविक उत्तर देने वालों को संपादित और इंगित करूंगा, या मेरा डिलीट कर दूंगा अगर कोई मेरे नाम के बाकी नामों के बारे में कहा जाएगा।
जॉन सॉन्डर्स

19

मैं नोटिस करता हूं कि बहुत से लोग सिफारिश कर रहे हैं Convert.ChangeType- यह कुछ मामलों के लिए काम करता है, लेकिन जैसे ही आप शामिल करना शुरू करते nullableहैं, आपको प्राप्त होना शुरू हो जाएगा InvalidCastExceptions:

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert.ChangeType-doesn_2700_t-handle-nullables.aspx

इसे संभालने के लिए कुछ साल पहले एक रैपर लिखा गया था, लेकिन यह बिल्कुल सही नहीं है।

http://weblogs.asp.net/pjohnson/archive/2006/02/07/Convert.ChangeType-doesn_2700_t-handle-nullables.aspx


13

मैंने 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);
}

मुझे धन्यवाद कहना होगा क्योंकि मैं इस मामले से मिला था और यह एकमात्र समाधान है। धन्यवाद ~!
Franva

11

आप एक प्रकार कनवर्टर (कोई त्रुटि जाँच नहीं) का उपयोग कर सकते हैं:

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

कोड को व्यवस्थित करने के मामले में, आप एक तरह का मिक्सकिन बना सकते हैं जिसके परिणामस्वरूप कोड इस प्रकार होगा:

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 { ... }

क्या कोई विशेष कारण है कि आपने केवल उपयोग करने के बजाय मार्कर इंस्टेरफेस को क्यों जोड़ा object?
ग्रू

1
हां, मार्कर इंटरफ़ेस एक्सटेंशन विधियों को जोड़ने के लिए प्लेसहोल्डर के रूप में कार्य करता है। उपयोग objectकरने से सभी वर्गों में विस्तार विधियों को जोड़ा जाएगा, जो आम तौर पर वांछनीय नहीं है।
जार्डो

6

तुम शायद 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);

5

का उपयोग कर Convert.ChangeTypeऔर से बदलने के लिए प्रकार हो रही है PropertyInfo.PropertyType

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

4

मैं इसका उत्तर एक सामान्य उत्तर के साथ दूंगा। आमतौर पर ये उत्तर छापों के साथ काम नहीं करते हैं। यहां एक कार्यशील संस्करण है जिसमें छापे भी हैं।

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); 

1
यह स्वीकृत उत्तर होना चाहिए। यह GUIDs <3 के साथ भी काम करता है। धन्यवाद, अली (वह मेरी बेटी का उपनाम है)
Cătălin Rădoi

3

या आप कोशिश कर सकते हैं:

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

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

2

यदि आप मेट्रो ऐप लिख रहे हैं, तो आपको अन्य कोड का उपयोग करना चाहिए:

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");

0

निम्नलिखित कोड का उपयोग करके अपनी समस्या को हल करना चाहिए:

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

-9

क्या आप परावर्तन के साथ खेलना चाहते हैं या क्या आप सॉफ्टवेयर का उत्पादन टुकड़ा बनाना चाहते हैं? मैं सवाल करूंगा कि आप संपत्ति सेट करने के लिए प्रतिबिंब का उपयोग क्यों कर रहे हैं।

Double new_latitude;

Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;

1
आपको इस बात का सम्मान करना चाहिए कि लोग क्या करने का प्रयास करते हैं और न कि आपको लगता है कि उन्हें क्या करना चाहिए। Downvoted। (से GenericProgramming.exe:ReflectionBenefits())
Петър Петров
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.