मैं नीचे के रूप में मेरी सेवा कक्षाओं में से एक में एपीआई बुला रहा हूँ:
public GetCustomerApiResponse SearchCustomerByEmail(string email)
{
GetCustomerApiResponse customerApiResponse = null;
try
{
var requestBody = JsonConvert.SerializeObject(new
{
content = $@"{{""Email"":""{email}""}}",
key = _apiEnvironment,
name = "search-customer"
});
var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var res = _client.PostAsync(_baseUrl, content).Result.Content.ReadAsStringAsync().Result;
customerApiResponse = JsonConvert.DeserializeObject<GetCustomerApiResponse>(res);
}
catch
{
// ignored
}
return customerApiResponse;
}
यहाँ, मैं GetCustomerApiResponse
प्रकार का Deserialized डेटा लौटा रहा हूँ। मैं पकड़ में विभिन्न प्रतिक्रिया प्रकार वापस करना चाहता हूं (उदाहरण के लिए GetCustomerApiResponseError
टाइप करें)। इसे कैसे हासिल करें?
4 जवाब
यह मानते हुए कि यदि आप अपवाद फेंकते हैं तो आप कुछ करना चाहते हैं, मैं अनुशंसा करता हूं कि आप ऐसा कुछ और करें:
public GetCustomerApiResponse SearchCustomerByEmail(string email)
{
try {}
catch(Exception ex)
{
throw MyException(ex);
}
return customerApiResponse;
}
जहां MyException
ऐसा दिखता है:
public MyException : Exception
{
public MyException(Exception innerException) : base(innerException) {}
}
और कॉलिंग कोड इस तरह दिखता है:
try
{
GetCustomerApiResponse response = SearchCustomerByEmail(email);
}
catch(MyException ex)
{
//do whatever you need to happen if it fails.
}
इस तरह कॉलिंग कोड को पता चलता है कि एक अपवाद फेंका गया है (यहां कोई छिपी हुई कार्यक्षमता नहीं है) लेकिन आप उस अपवाद को एक सुरुचिपूर्ण तरीके से भी संभाल सकते हैं। यदि आप अपने हैंडलिंग लॉजिक के लिए अधिक जानकारी प्रदान करना चाहते हैं, तो आप MyException
का विस्तार कर सकते हैं।
दुर्भाग्य से आप विभिन्न प्रकार वापस नहीं कर सकते जब तक कि आप मूल प्रकार से निपट नहीं रहे हैं।
यदि आप कोड को कॉल करके अपवाद को संभालने के अलावा किसी विशिष्ट तरीके से त्रुटि को संभालना चाहते हैं, तो आप एक GetCustomerApiResult
वापस कर सकते हैं
public class GetCustomerApiResponse {
GetCustomerApiResponse CustomerApiResponse { get; set; }
GetCustomerApiResponse CustomerApiError { get; set; }
}
तब आप कर सकते हैं
public GetCustomerApiResult SearchCustomerByEmail(string email)
{
var result = new CuscustomerApiResult();
try
{
...
customerApiResult.CustomerApiResponse = JsonConvert.DeserializeObject<GetCustomerApiResponse>(res);
}
catch
{
// Handle the exception but return some error information
customerApiResult.CustomerApiError = ...
}
return customerApiResponse;
}
और अपने कॉलिंग कोड में आप जांच सकते हैं कि customerApiResult.CustomerApiError
त्रुटि के लिए शून्य नहीं है या सफलता के लिए customerApiResult.CustomerApiResult
जांचें।
सबसे पहले, एक नियम के रूप में, आपको वास्तव में अपवादों (ए.के.ए. निगल) अपवादों को अनदेखा नहीं करना चाहिए।
निगलने वाले अपवादों को एक कोड गंध माना जाता है और आमतौर पर अच्छे कारणों के लिए उनका अपमान किया जाता है।
ऐसा कहा जा रहा है, ऐसे मामले हैं जब आप अपवाद नहीं चाहते हैं या आपको अपवाद फेंकने की आवश्यकता नहीं है - लेकिन फिर भी कॉलिंग विधि को सूचित करें कि आपको कुछ समस्या का सामना करना पड़ा है और वह अपेक्षित परिणाम नहीं दे सकता है।
ऐसा उपयोग-मामला तब हो सकता है जब आप किसी सेवा से प्राप्त कुछ जटिल डेटा को सत्यापित करने का प्रयास कर रहे हों - उदाहरण के लिए, सुनिश्चित करें कि आपके लिए आवश्यक सभी गुणों में वास्तव में वे मान हैं जिनके साथ आप काम कर सकते हैं (उनमें से कोई भी डिफ़ॉल्ट नहीं है या ऐसा ही कुछ)।
एक "अमान्य" डेटा सेवा से वापस आने की उम्मीद की जा सकती है और इसलिए ऐसे मामले में अपवाद फेंकना सबसे अच्छा अभ्यास नहीं हो सकता है - इन स्थितियों के लिए मुझे वह उपयोग करना पसंद है जिसे मैंने Result<T>
कहा है।
Result<T>
मूल्य पर एक रैपर वर्ग जिसे अन्यथा वापस किया जाना चाहिए - कुछ और गुणों के साथ - सफलता या विफलता का संकेत देने वाला एक बूल और वैकल्पिक रूप से एक त्रुटि विवरण युक्त एक स्ट्रिंग।
आपके मामले में, कोड इस तरह दिखेगा:
public Result<GetCustomerApiResponse> SearchCustomerByEmail(string email)
{
try
{
var requestBody = JsonConvert.SerializeObject(new
{
content = $@"{{""Email"":""{email}""}}",
key = _apiEnvironment,
name = "search-customer"
});
var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var res = _client.PostAsync(_baseUrl, content).Result.Content.ReadAsStringAsync().Result;
return Result<GetCustomerApiResponse>
.Success(JsonConvert.DeserializeObject<GetCustomerApiResponse>(res));
}
catch(Exception ex)
{
return Result<GetCustomerApiResponse>
.Fail(ex.Message); // or ex.ToString() if you need more information
}
}
कॉलिंग कोड ऐसा कुछ करेगा:
var result = SearchCustomerByEmail(email);
if(!result.Succeeded)
{
Log(result.ErrorDescription);
// Perhaps show the error description to the user (if you have one)
return;
}
var customer = result.Value;
... rest of the code here
आप इसके बारे में परिणाम और परिणाम का उपयोग करके गैर असाधारण त्रुटियों को संभालना।
मैं एक वर्ग CustomerApiResult
का उपयोग करूंगा जिसमें एक संपत्ति GetCustomerApiResponse
है और साथ ही ValidResponse
+ IEnumerable<string> ResponseErrors
।
public class CustomerApiResult
{
// make the constructor private and use factory methods as below
private CustomerApiResult(
bool validResponse,
GetCustomerApiResponse apiResponse,
//... other properties...,
string invalidReason,
IEnumerable<string> responseErrors)
{
ValidResponse = validResponse;
CustomerApiResponse = apiResponse;
// other properties ...;
InvalidReason = invalidReason;
ResponseErrors = responseErrors ?? Enumerable.Empty<string>();
}
public bool ValidResponse { get; }
public GetCustomerApiResponse CustomerApiResponse { get; }
// other properties
public string InvalidReason { get; }
public IEnumerable<string> ResponseErrors { get; private set; }
public static CustomerApiResult Valid(
GetCustomerApiResponse apiResponse,
// other properties,
IEnumerable<string> responseErrors = null)
=> new CustomerApiResult(true, apiResponse, null, responseErrors);
public static CustomerApiResult Invalid(
GetCustomerApiResponse apiResponse,
// other properties,
string invalidReason = null,
IEnumerable<string> responseErrors = null)
=> new CustomerApiResult(false, apiResponse, invalidReason, responseErrors);
}
अब आप इसे इस तरह इस्तेमाल कर सकते हैं:
public CustomerApiResult SearchCustomerByEmail(string email)
{
try
{
var requestBody = JsonConvert.SerializeObject(new
{
content = $@"{{""Email"":""{email}""}}",
key = _apiEnvironment,
name = "search-customer"
});
var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var res = _client.PostAsync(_baseUrl, content).Result.Content.ReadAsStringAsync().Result;
return CustomerApiResult.Valid(JsonConvert.DeserializeObject<GetCustomerApiResponse>(res));
}
catch(Exception ex)
{
return CustomerApiResult.Invalid(null, $"Could not convert to {nameof(GetCustomerApiResponse)}", new[]{ex.Message});
}
}
इसलिए मैं परिवर्तित वस्तु नहीं लौटाता, लेकिन एक एपीआई-परिणाम वस्तु जिसमें वस्तु (या अशक्त) होती है और एक ValidResponse
संपत्ति होती है जिसे आपको पहले जांचना चाहिए।
तो उदाहरण के लिए:
CustomerApiResult result = _api.SearchCustomerByEmail("jon.doe@gmail.com");
if(result.ValidResponse)
{
GetCustomerApiResponse customer = result.CustomerApiResponse;
// do something with the customer ...
}
else
{
// log the response errors and/or the InvalidReason and inform the user
}
इस दृष्टिकोण के फायदों में से एक यह है कि आप तर्क का उपयोग कर सकते हैं, भले ही कोई अपवाद न हो (इसलिए उदाहरण के लिए एपीआई या तार्किक दोष से एक अमान्य परिणाम है)। एक और फायदा यह है कि आप ऊपरी एप्लिकेशन परतों पर लौटने से पहले एपीआई में लगातार कई कॉल के साथ इसका इस्तेमाल कर सकते हैं और प्रतिक्रिया-त्रुटियों को एकत्र कर सकते हैं (उदाहरण के लिए उन्हें अलग से लॉग इन करने के लिए)। आप इसका उपयोग यह तय करने के लिए भी कर सकते हैं कि क्या आप अगले चरण के साथ जारी रख सकते हैं यदि पिछली कॉल में पहले से ही कोई अमान्य प्रतिक्रिया है या यदि वह कॉल पूरे वर्कफ़्लो को रोकने के लिए पर्याप्त महत्वपूर्ण नहीं थी।
Result<T>
उत्तर की तरह है, इस अपवाद के साथ कि मेरा प्रस्तावित समाधान अधिक सामान्य है। मुझे अपनी एकल ErrorDescription
संपत्ति से अधिक IEnumerable<string> responseErrors
का उपयोग पसंद है, लेकिन दूसरी ओर, मुझे यह तथ्य बेहतर लगता है कि मेरा प्रस्तावित समाधान अधिक सामान्य-उद्देश्य वाला है। ऑल-इन-ऑल, +1।
CustomerId
जैसी संपत्ति प्राप्त करते हैं। और परिणाम वर्ग में इसे बेनकाब करना चाहते हैं। लेकिन हाँ, एक सामान्य दृष्टिकोण एक अच्छा तरीका है, इसलिए शायद हमारे उत्तरों का मिश्रण अच्छा होगा।
संबंधित सवाल
नए सवाल
c#
C # (उच्चारण "तेज देखें") Microsoft द्वारा विकसित एक उच्च स्तरीय, सांख्यिकीय रूप से टाइप किया हुआ, बहु-प्रतिमान प्रोग्रामिंग भाषा है। C # कोड आमतौर पर Microsoft के .NET परिवार के टूल और रन-टाइम को लक्षित करता है, जिसमें .NET फ्रेमवर्क, .NET कोर और Xamarin अन्य शामिल हैं। C # या C # के औपचारिक विनिर्देश में लिखे गए कोड के बारे में प्रश्नों के लिए इस टैग का उपयोग करें।
GetCustomerApiResponse
औरGetCustomerApiResponseError
के लिए कुछ आधार प्रकार होना चाहिए और बहुरूपता का उपयोग करना चाहिए, याcatch
खंड मेंreturn
का उपयोग करना चाहिए।object
वापस आ सकते हैं, लेकिन मैं इसकी अनुशंसा नहीं करूंगा। सी # में किसी कारण से मजबूत प्रकार हैं। ऐसा लगता है कि आप वास्तव में यहां क्या करना चाहते हैं एक टाइप किया गया अपवाद फेंकना है?