रिफ्लेक्शन तब होता है जब मैनेज्ड कोड अपने स्वयं के मेटाडेटा को पढ़कर असेंबलीज ढूंढ सकता है। अनिवार्य रूप से, यह कोड को उसी सिस्टम के भीतर अन्य कोड का निरीक्षण करने की अनुमति देता है। C# में रिफ्लेक्शन के साथ, हम डायनामिकली एक टाइप का इंस्टेंस बना सकते हैं और उस टाइप को मौजूदा ऑब्जेक्ट से बाइंड कर सकते हैं। इसके अलावा, हम मौजूदा ऑब्जेक्ट से टाइप प्राप्त कर सकते हैं और उसकी प्रॉपर्टीज एक्सेस कर सकते हैं।
समस्या: स्ट्रिंग से टाइप्ड प्रॉपर्टी में कन्वर्जन
मान लीजिए हमारे पास double टाइप की प्रॉपर्टी है लेकिन रनटाइम पर हमारे पास वैल्यू स्ट्रिंग के रूप में है। हम Convert.ChangeType() का उपयोग कर सकते हैं - यह हमें रनटाइम जानकारी का उपयोग करके किसी भी IConvertible टाइप का प्रतिनिधित्व फॉर्मेट बदलने की अनुमति देता है।
उदाहरण: रिफ्लेक्शन के साथ Convert.ChangeType()
using System;
using System.Reflection;
namespace DemoApplication
{
class Program
{
static void Main()
{
Circle circle = new Circle();
string value = "6.5";
Console.WriteLine($"स्ट्रिंग वैल्यू: {value}");
// प्रॉपर्टी इन्फो प्राप्त करें
PropertyInfo propertyInfo = circle.GetType().GetProperty("Radius");
// स्ट्रिंग को प्रॉपर्टी के वास्तविक टाइप (double) में कन्वर्ट करें और सेट करें
propertyInfo.SetValue(circle, Convert.ChangeType(value, propertyInfo.PropertyType), null);
// वैल्यू पढ़कर सत्यापित करें
var radius = circle.GetType().GetProperty("Radius").GetValue(circle, null);
Console.WriteLine($"Radius: {radius}");
Console.WriteLine($"Radius टाइप: {radius.GetType()}");
Console.ReadLine();
}
}
class Circle
{
public double Radius { get; set; }
}
}
आउटपुट
स्ट्रिंग वैल्यू: 6.5 Radius: 6.5 Radius टाइप: System.Double
विभिन्न टाइप्स के लिए जेनेरिक हेल्पर मेथड
public static class ReflectionHelper
{
///
/// रिफ्लेक्शन का उपयोग करके ऑब्जेक्ट पर प्रॉपर्टी सेट करता है, स्ट्रिंग से ऑटोमेटिक टाइप कन्वर्जन के साथ
///
public static void SetPropertyFromString(object obj, string propertyName, string value)
{
if (obj == null) throw new ArgumentNullException(nameof(obj));
if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("प्रॉपर्टी नाम आवश्यक है");
var propertyInfo = obj.GetType().GetProperty(propertyName,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (propertyInfo == null)
throw new ArgumentException($"प्रॉपर्टी '{propertyName}' टाइप {obj.GetType().Name} पर नहीं मिली");
if (!propertyInfo.CanWrite)
throw new InvalidOperationException($"प्रॉपर्टी '{propertyName}' रीड-ओनली है");
try
{
object convertedValue;
// नल या खाली स्ट्रिंग हैंडलिंग
if (string.IsNullOrEmpty(value))
{
if (propertyInfo.PropertyType.IsValueType &&
Nullable.GetUnderlyingType(propertyInfo.PropertyType) == null)
{
throw new ArgumentException($"वैल्यू टाइप प्रॉपर्टी '{propertyName}' को नल नहीं किया जा सकता");
}
convertedValue = null;
}
// एनम हैंडलिंग
else if (propertyInfo.PropertyType.IsEnum)
{
convertedValue = Enum.Parse(propertyInfo.PropertyType, value, ignoreCase: true);
}
// GUID हैंडलिंग
else if (propertyInfo.PropertyType == typeof(Guid))
{
convertedValue = Guid.Parse(value);
}
// DateTime हैंडलिंग
else if (propertyInfo.PropertyType == typeof(DateTime))
{
convertedValue = DateTime.Parse(value, CultureInfo.InvariantCulture);
}
// TimeSpan हैंडलिंग
else if (propertyInfo.PropertyType == typeof(TimeSpan))
{
convertedValue = TimeSpan.Parse(value);
}
// सामान्य कन्वर्जन (IConvertible के लिए काम करता है)
else
{
convertedValue = Convert.ChangeType(value, propertyInfo.PropertyType, CultureInfo.InvariantCulture);
}
propertyInfo.SetValue(obj, convertedValue);
}
catch (Exception ex) when (ex is FormatException || ex is OverflowException || ex is ArgumentException)
{
throw new InvalidOperationException(
$"वैल्यू '{value}' को टाइप {propertyInfo.PropertyType.Name} में कन्वर्ट नहीं कर सकते: {ex.Message}", ex);
}
}
}
// उपयोग
var person = new Person();
ReflectionHelper.SetPropertyFromString(person, "Age", "25");
ReflectionHelper.SetPropertyFromString(person, "Name", "John");
ReflectionHelper.SetPropertyFromString(person, "BirthDate", "1990-01-15");
ReflectionHelper.SetPropertyFromString(person, "IsActive", "true");
ReflectionHelper.SetPropertyFromString(person, "Salary", "50000.50");
सपोर्टेड टाइप्स (IConvertible के माध्यम से)
| टाइप | उदाहरण स्ट्रिंग |
|---|---|
| int, long, short, byte | "123", "-456" |
| float, double, decimal | "3.14", "1.5e2" |
| bool | "true", "false", "True", "False" |
| char | "A" |
| DateTime | "2023-12-25", "12/25/2023" |
| Guid | "12345678-1234-1234-1234-123456789012" |
| Enum | "Value1" (केस-इनसेंसिटिव) |
सावधानियां और सर्वोत्तम अभ्यास
- प्रदर्शन: रिफ्लेक्शन डायरेक्ट प्रॉपर्टी एक्सेस से धीमा है - हॉट पाथ्स में उपयोग न करें
- एक्सेप्शन हैंडलिंग: हमेशा कन्वर्जन एरर्स को ग्रेसफुली हैंडल करें
- कल्चर:
CultureInfo.InvariantCultureका उपयोग करें सुसंगत पार्सिंग के लिए - नल हैंडलिंग: नल करने योग्य वैल्यू टाइप्स (
int?,double?) को उचित तरीके से हैंडल करें - सुरक्षा: अनट्रस्टेड इनपुट के साथ रिफ्लेक्शन का उपयोग न करें बिना मान्यता के
आधुनिक विकल्प: System.Text.Json
// JSON डिसीरियलाइज़ेशन के लिए (अधिक मजबूत)
var json = "{\"Radius\": 6.5}";
var circle = JsonSerializer.Deserialize(json);
// या डायनामिक ऑब्जेक्ट के लिए
var obj = JsonSerializer.Deserialize(json);
double radius = obj.GetProperty("Radius").GetDouble();