2011-06-29 11 views
8

कल्पना कीजिए कि कक्षा एक उदाहरण Load() विधि के साथ है।स्टेटिक तरीके से निर्भरता इंजेक्शन का उपयोग कैसे करें?

जब Load() विधि कहा जाता है, तो यह ऑर्डर विवरण पुनर्प्राप्त करता है उदा।

var orders = Order.GetAll(customerId, ...); 

GetAll()Order वर्ग के एक स्थिर तरीका है और इनपुट पैरामीटर Customer वर्ग में परिभाषित क्षेत्र हैं।

आप देख सकते हैं, OrderCustomer वर्ग के एक निर्भरता, हालांकि, मैं सिर्फ एक IOrder नहीं बना पा रहा है और वहाँ यह इंजेक्षन इंटरफेस स्थिर पद्धतियां नहीं हो सकतीं के रूप में है।

इसलिए, प्रश्न यह है कि मैं इस उदाहरण में निर्भरता इंजेक्शन कैसे पेश कर सकता हूं?

मैं GetAll() एक उदाहरण विधि बनाना नहीं चाहता क्योंकि यह एक स्थिर विधि है और इसे इस तरह से रखने की आवश्यकता है।

उदाहरण के लिए, मैंने अपने डिजाइन में उपयोगिता कक्षाओं का उपयोग किया है, जिनमें से अधिकांश में स्थिर विधियां हैं।

उत्तर

9

यदि आप स्थिर विधि को रखें, तो मैं स्थिर कॉल को एक रिपोजिटरी ऑब्जेक्ट में लपेटूंगा।

इस तरह

:

interface IOrderRepository { 
    IEnumerable<IOrder> GetAll(customerId, ..); 
} 

class OrderRepository : IOrderRepository { 
    IEnumerable<IOrder> GetAll(customerId, ...) 
    { 
    Order.GetAll(customerId,...); // The original static call. 
    } 
} 

अब आप अपने Customer वर्ग में इस भंडार इंजेक्षन।

(मैं आप यह कर रहे हैं ताकि आप परीक्षण प्रयोजनों के लिए कार्यावधि में नकली IOrders इंजेक्षन कर सकते हैं यह सोचते हैं रहा हूँ। मैं कहना चाहिए कि सामान्य रूप में, स्थिर तरीकों का परीक्षण करने के लिए एक गंभीर बाधा है।)

+0

धन्यवाद, क्या ये भंडार वर्ग और इंटरफेस डेटा एक्सेस लेयर का हिस्सा होंगे? माई ऑर्डर क्लास ऑर्डर टेबल से मैप की गई एक व्यावसायिक इकाई है (LINQ से SQL का उपयोग करके)। –

+0

@ user133212 यह आपके मौजूदा फ़ंक्शन के आसपास सिर्फ एक रैपर है। इसलिए जहां भी यह कार्य तार्किक रूप से परत-वार से संबंधित है, मैं भी रैपर डालूंगा। –

3

के रूप में देखकर अपने ऑर्डर लाने के लिए कुल रूट आपका ग्राहक मॉडल है I दृढ़ता से सलाह देता है कि आप ग्राहक भंडार बनाएं और जो भी सेवा की आवश्यकता हो उसे इंजेक्ट करें।

public class CustomerService 
{ 
    private readonly ICustomerRepository _customerRepository; 

    public CustomerService(ICustomerRepository customerRepository) 
    { 
     if (customerRepository == null) 
     { 
      throw new ArgumentNullException("customerRepository"); 
     } 

     _customerRepository = customerRepository; 
    } 

    public IEnumerable<IOrder> GetOrdersForCustomerId(int customerId) 
    { 
     return _customerRepository.GetOrdersForCustomerId(customerId); 
    } 
} 

public interface ICustomerRepository 
{ 
    IEnumerable<IOrder> GetOrdersForCustomerId(int customerId); 
} 

class CustomerRepository : ICustomerRepository 
{ 
    public IEnumerable<IOrder> GetOrdersForCustomerId(int customerId) 
    { 
     throw new NotImplementedException(); 
    } 
} 
0

समारोह सूचक इंजेक्शन

TLDR:

Customer वर्ग में एक समारोह सूचक सम्मिलित करें

यहाँ एक उदाहरण है। इस फ़ंक्शन पॉइंटर का मान Order.GetAll उत्पादन में और MockOrder.GetAll परीक्षणों में हो सकता है।

उदाहरण:

निर्भरता (समस्याग्रस्त स्थिर समारोह हम पर निर्भर करते हैं):

class Customer { 
    func Init(getAllOrdersFunction) { // Arg is a func pointer 
     self.getAllOrdersFunction = getAllOrdersFunction 
    } 

    func Load() { 
     var orders = self.getAllOrdersFunction() 
     // Do stuff... 
    } 
} 

उत्पादन:

class Order { 
    static func GetAll() -> [Order] { 
     var orders = ... // Load from production source 
     return orders 
    } 
} 

हमारे निर्भर वर्ग (स्थिर समारोह पर निर्भर करता है) क्लाइंट क्लास (निर्भरता इंजेक्शन करता है पर):

class BusinessLogicManager { 
    func DoBusinessLogic() { 
     var customer = Customer(Order.GetAll) // Prod func injected here 
     customer.Load() 
     // Do stuff... 
    } 
} 

परीक्षण ग्राहक वर्ग (कैसे इकाई परीक्षण एक नकली निर्भरता) इंजेक्षन कर सकते हैं:

class CustomerUnitTests { 
    static func GetFakeOrders() { 
     var orders = ... // Hardcoded test data 
     return orders 
    } 

    func TestLoad() { 
     var customer = Customer(CustomerUnitTests.GetFakeOrders) // Fake func injected here 
     customer.Load() 
     // Verify results given known behavior of GetFakeOrders 
    } 
} 

चर्चा:

कैसे आप वास्तव में होगा "समारोह सूचक" इंजेक्षन आपकी भाषा में उपलब्ध वाक्यविन्यास और सुविधाओं पर निर्भर करता है। यहां मैं सिर्फ सामान्य अवधारणा के बारे में बात कर रहा हूं।

यह बिल्कुल एक सुंदर समाधान नहीं है। यह संभवतः आसान होगा यदि आप GetAll को एक इंस्टेंस विधि (शायद OrdersLoader ऑब्जेक्ट पेश करके या पॉल फिलिप्स के उत्तर का उपयोग करके) बदल सकते हैं। लेकिन यदि आप वास्तव में इसे एक स्थिर कार्य के रूप में रखना चाहते हैं, तो यह समाधान काम करेगा।

संबंधित मुद्दे