आप जो हासिल करना चाहते हैं उस पर निर्भर करता है।
1) यदि आप बस अपने कोड को साफ, और दोहराव प्रकार की जाँच के दूर करने के लिए कोशिश कर रहे हैं, तो क्या आप क्या करना चाहते एक विधि में अपने चेक को केंद्रीकृत, comme है
public static T To<T> (this string stringValue)
{
T value = default (T);
if (typeof (T) == typeof (DateTime))
{
// insert custom or convention System.DateTime
// deserialization here ...
}
// ... add other explicit support here
else
{
throw new NotSupportedException (
string.Format (
"Cannot convert type [{0}] with value [{1}] to type [{2}]." +
" [{2}] is not supported.",
stringValue.GetType(),
stringValue,
typeof (T)));
}
return value;
}
2) यदि आप होगा मूल प्रकारों के लिए कुछ अधिक सामान्यीकृत की तरह, आप Thomas Levesquesuggests जैसे कुछ कोशिश कर सकते हैं - हालांकि सच में, मैंने इसे स्वयं नहीं किया है, मैं हाल ही में [हालिया?] एक्सटेंशन से Convert
पर अपरिचित हूं। यह भी एक बहुत अच्छा सुझाव है।
3) असल में, आप शायद 1) और 2 दोनों को एक ही एक्सटेंशन में विलय करना चाहते हैं जो आपको मूल मूल्य रूपांतरण और स्पष्ट जटिल प्रकार के समर्थन का समर्थन करने में सक्षम बनाता है।
4) यदि आप पूरी तरह से "हाथ मुक्त" होना चाहते हैं, तो आप सादे पुराने deserialization [एक्सएमएल या बाइनरी, या तो/या] के लिए भी डिफ़ॉल्ट हो सकता है। बेशक, यह आपके इनपुट को बाधित करता है - यानी सभी इनपुट एक्सएमएल या बाइनरी प्रारूप को अनुमोदित होना चाहिए। ईमानदारी से, यह शायद अधिक है, लेकिन उल्लेख करने लायक है।
बेशक, ये सभी विधियां अनिवार्य रूप से वही काम करती हैं। उनमें से किसी भी में कोई जादू नहीं है, किसी बिंदु पर कोई एक रैखिक लुकअप कर रहा है [चाहे यह अनुक्रमिक if-clauses या .Net रूपांतरण और क्रमबद्धता सुविधाओं के माध्यम से हुड के नीचे एक अंतर्निहित रूप है।
5) यदि आप प्रदर्शन में सुधार करना चाहते हैं, तो आप अपनी रूपांतरण प्रक्रिया के "लुकअप" भाग को बेहतर बनाना चाहते हैं। एक स्पष्ट "समर्थित प्रकार" सूची बनाएं, प्रत्येक प्रकार किसी सरणी में किसी अनुक्रमणिका से संबंधित है। कॉल पर टाइप निर्दिष्ट करने के बजाय, आप इंडेक्स निर्दिष्ट करते हैं।
संपादित करें:, जबकि रैखिक रूप से दिखने वाला साफ और तेज़ है, यह भी मेरे साथ होता है यदि उपभोक्ता ने रूपांतरण कार्यों को आसानी से प्राप्त किया और सीधे उन्हें बुलाया तो यह तेज़ होगा। यही कारण है, उपभोक्ता जो भी लिखते इसे करने के लिए [यह एक दिया जाता है] कन्वर्ट करने के लिए चाहते हैं, इसलिए यदि यह एक समय में कई मदों में परिवर्तित करने की जरूरत है जानता है,
// S == source type
// T == target type
public interface IConvert<S>
{
// consumers\infrastructure may now add support
int AddConversion<T> (Func<S, T> conversion);
// gets conversion method for local consumption
Func<S, T> GetConversion<T>();
// easy to use, linear look up for one-off conversions
T To<T> (S value);
}
public class Convert<S> : IConvert<S>
{
private class ConversionRule
{
public Type SupportedType { get; set; }
public Func<S, object> Conversion { get; set; }
}
private readonly List<ConversionRule> _map = new List<ConversionRule>();
private readonly object _syncRoot = new object();
public void AddConversion<T> (Func<S, T> conversion)
{
lock (_syncRoot)
{
if (_map.Any (c => c.SupportedType.Equals (typeof (T))))
{
throw new ArgumentException (
string.Format (
"Conversion from [{0}] to [{1}] already exists. " +
"Cannot add new conversion.",
typeof (S),
typeof (T)));
}
ConversionRule conversionRule = new ConversionRule
{
SupportedType = typeof(T),
Conversion = (s) => conversion (s),
};
_map.Add (conversionRule);
}
}
public Func<S, T> GetConversion<T>()
{
Func<S, T> conversionMethod = null;
lock (_syncRoot)
{
ConversionRule conversion = _map.
SingleOrDefault (c => c.SupportedType.Equals (typeof (T)));
if (conversion == null)
{
throw new NotSupportedException (
string.Format (
"Conversion from [{0}] to [{1}] is not supported. " +
"Cannot get conversion.",
typeof (S),
typeof (T)));
}
conversionMethod =
(value) => ConvertWrap<T> (conversion.Conversion, value);
}
return conversionMethod;
}
public T To<T> (S value)
{
Func<S, T> conversion = GetConversion<T>();
T typedValue = conversion (value);
return typedValue;
}
// private methods
private T ConvertWrap<T> (Func<S, object> conversion, S value)
{
object untypedValue = null;
try
{
untypedValue = conversion (value);
}
catch (Exception exception)
{
throw new ArgumentException (
string.Format (
"Unexpected exception encountered during conversion. " +
"Cannot convert [{0}] [{1}] to [{2}].",
typeof (S),
value,
typeof (T)),
exception);
}
if (!(untypedValue is T))
{
throw new InvalidCastException (
string.Format (
"Converted [{0}] [{1}] to [{2}] [{3}], " +
"not of expected type [{4}]. Conversion failed.",
typeof (S),
value,
untypedValue.GetType(),
untypedValue,
typeof (T)));
}
T typedValue = (T)(untypedValue);
return typedValue;
}
}
और यह
// as part of application innitialization
IConvert<string> stringConverter = container.Resolve<IConvert<string>>();
stringConverter.AddConversion<int> (s => Convert.ToInt32 (s));
stringConverter.AddConversion<Color> (s => CustomColorParser (s));
...
// a consumer elsewhere in code, say a Command acting on
// string input fields of a form
//
// NOTE: stringConverter could be injected as part of DI
// framework, or obtained directly from IoC container as above
int someCount = stringConverter.To<int> (someCountString);
Func<string, Color> ToColor = stringConverter.GetConversion <Color>();
IEnumerable<Color> colors = colorStrings.Select (s => ToColor (s));
के रूप में इस्तेमाल किया जाएगा
मैं इस बाद के दृष्टिकोण को बहुत पसंद करता हूं, क्योंकि यह आपको पूर्ण रूपांतरण पर नियंत्रण देता है। यदि आप कैसल विंडसर या यूनिटी जैसे नियंत्रण का एक उलटा [आईओसी] कंटेनर का उपयोग करते हैं, तो इस सेवा का इंजेक्शन आपके लिए किया जाता है। इसके अलावा, क्योंकि यह उदाहरण आधारित है, तो आपके पास कई उदाहरण हो सकते हैं, प्रत्येक के अपने रूपांतरण नियमों के सेट के साथ - यदि उदाहरण के लिए, आपके पास एकाधिक उपयोगकर्ता नियंत्रण हैं, प्रत्येक का अपना DateTime
या अन्य जटिल स्ट्रिंग प्रारूप उत्पन्न होता है।
हेक, भले ही आप एक ही लक्ष्य प्रकार के लिए एकाधिक रूपांतरण नियमों का समर्थन करना चाहते हैं, यह भी संभव है, आपको बस निर्दिष्ट करने के लिए विधि पैरामीटर का विस्तार करना होगा।
आप यह नहीं दिखाते कि कैसे 'पी' परिभाषित किया गया है, टाइपो? – Hogan
कम से कम, आपको 'is' ऑपरेटर का उपयोग करना चाहिए। मैंने प्रतिबिंब का उपयोग किये बिना सही तरीके से जांचने के लिए अपना प्रश्न अपडेट कर दिया है। –
@ डेविड पेफर, 'is' ऑपरेटर गलत तरीके से लागू किया गया है। इस संदर्भ में 'is' सच कभी वापस नहीं आएगा [' propType' हमेशा टाइप प्रकार 'प्रकार' होगा। आप 'propType == टाइपऑफ (डेटटाइम)' –