2011-09-19 7 views
7

साथ सामान्य भंडार करने के लिए मैं इस प्रकार मेरी सामान्य भंडार की स्थापना की है:कैसे निर्भरता इंजेक्शन

public interface IRepository<T> : IDisposable where T : Entity 
{ 
    T GetById(int id); 
} 

public abstract class Repository<T> : IRepository<T> where T : Entity 
{ 
    protected readonly SqlDbContext _context = new SqlDbContext(); 

    public T GetById(int id) 
    { 
     return _context.Set<T>().Find(id); 
    } 
} 

मेरी MVC अनुप्रयोग में निर्भरता इंजेक्शन सक्षम करने के लिए मैं भी एक उत्पाद इंटरफ़ेस बनाने के बाद से हस्ताक्षर अलग है। यह अन्य भंडारों के लिए भी मामला है।

public interface IProductRepository : IRepository<Product> 
{ 
    IEnumerable<Product> GetDiscountedProducts(); 
} 

और कार्यान्वयन (विरासत ध्यान दें)

public class ProductRepository : Repository<Product>, IProductRepository 
{ 
    public IEnumerable<Product> GetDiscountedProducts() 
    { 
     return _context.Set<Product>().Where(x=>x)... 
    }   
} 

अंत भंडार एकता

public HomeController(IProductRepository repository) 
{ 
} 

का उपयोग कर MVC नियंत्रक में इंजेक्शन हो जाता है यह सिर्फ मुझे है या इस विरासत श्रृंखला एक है थोड़ा गन्दा यहाँ? क्या इस डिजाइन को बेहतर बनाने का कोई तरीका है?

+0

इम सोच क्या 'भंडार ' और 'IRepository द्वारा प्राप्त की है' पैटर्न जब यह 'IProductRepository' के रूप में पारित रहा है - आप 'रिपोजिटरी ' कार्यान्वयन कभी नहीं देख पाएंगे जब तक कि आप कास्ट न करें, इसलिए यह थोड़े बेकार है। – Tejs

+1

इस पर एक नज़र डालें: http://codebetter.com/gregyoung/2009/01/16/ddd-the-generic-repository/ – Dmitry

+0

यह प्रयास करने का प्रयास क्या है? (गंभीर प्रश्न) मेरे एमवीसी 3 प्रोजेक्ट के साथ मेरे पास क्या है, ऑब्जेक्ट्स (क्वेरीज़ एंड कमांड्स अला सीक्यूआरएस) के 2 सेट हैं, और उनमें से प्रत्येक एक LINQ के साथ आता है जो एक एकल रिपोजिटरी क्लास को हिट करता है जिसमें सभी डेटाबेस ऑब्जेक्ट्स तक पहुंच होती है। इस मामले में एकाधिक रिपॉजिटरीज़ मुझे कहाँ लाभ पहुंचाएंगे?(मुझे पहले से ही पता है कि प्रत्येक कमान/क्वेरी अपने वर्ग के नाम से सम्मेलन द्वारा क्या करती है) और यह भी निर्भरता इंजेक्शन कहां खेलता है? फिलहाल यह मेरे लिए अतिसंवेदनशील प्रतीत होता है, लेकिन मुझे जानने में दिलचस्पी है। –

उत्तर

6

मैं इस विशेष मामले के लिए IProductRepository से बचने के लिए सुझाव है (जब बस एक और बहुत विशिष्ट विधि जोड़ने) और मूल IRepository इंटरफेस को बढ़ाने के नीचे दिखाया गया है:

public interface IRepository<TEntity> : IDisposable 
       where TEntity : Entity 
{  
    TEntity GetById(int id); 
    IEnumerable<TEntity> List(IFilterCriteria criteria); 
} 

और फिर लागू

public sealed class ProductDiscountFilterCriteria : IFilterCriteria 
{ 
    // ... 
} 

लेकिन इस तरह के मामले में आपको किसी प्रश्न के मानदंडों को बदलने के लिए कुछ तर्क परिभाषित करना होगा, यह LINQ अभिव्यक्ति हो सकता है क्योंकि आप पहले ही LINQ का उपयोग कर रहे हैं। यदि इस तरह के क्रेटरिया अभिव्यक्ति दृष्टिकोण आपके मामले के लिए जटिल है - तो मैं आपके द्वारा प्रस्तावित दृष्टिकोण के साथ चिपकने का सुझाव दूंगा।

संपादित करें:IFilterCriteria बस है Query Object पैटर्न कार्यान्वयन

interface IFilterCriteria<TQuery> 
{ 
    TQuery ToQuery(); 
} 

public sealed class ProductDiscountFilterCriteria : IFilterCriteria<DynamicExpression> 
{ 
    public decimal Discount { get; private set; } 

    public DynamicExpression ToQuery() 
    { 
    // build expression for LINQ clause Where("Discount" > this.Discount) 
    } 
} 

या कच्चे एसक्यूएल मापदंड बिल्डर:

var products = productRepository.List<Product>(
          new DiscountFilterCriteria { Discount = 50 }); 
:

public sealed class ProductDiscountFilterCriteria : IFilterCriteria<string> 
{ 
    public decimal Discount { get; private set; } 

    public string ToQuery() 
    { 
    // simplified 
    return "WHERE Discount < " + this.Discount; 
    } 
} 

तो फिर आप की तरह इसका इस्तेमाल करने में सक्षम होगा

गतिशील LINQ उदाहरण और लेख:

+0

क्या आप फ़िल्टर अवधारणा को एक साधारण उदाहरण के साथ थोड़ा सा विस्तारित कर सकते हैं? – Fixer

+0

@ फ़िक्सर: मेरे उत्तर का हिस्सा संपादित करें देखें – sll