10

निनजेक्ट.एमवीसी 2.2.0.3 (after merge) के साथ एक एमवीसी 3-एप्लिकेशन में, सीधे नियंत्रकों में रिपोस्टोरियों को इंजेक्शन देने की बजाय मैं एक सेवा-परत बनाने की कोशिश कर रहा हूं जिसमें व्यवसायिक शामिल है और वहां repostories इंजेक्ट करें। मैं एक गतिशील वस्तु के रूप में सेवा-परत में ninject-DependencyResolver को पास करता हूं (क्योंकि मैं mvc को संदर्भित नहीं करना चाहता और न ही वहां निंदा करता हूं)। फिर मैं NinjectHttpAplicationModule में निर्दिष्ट बाइंडिंग और जीवनकाल के साथ भंडार प्राप्त करने के लिए GetService पर कॉल करता हूं। संपादित करें: संक्षेप में, यह असफल रहा।Ninject.MVC3, पास निर्भरता रीसोलवर सेवा-परत के लिए?

इस मामले में आईओसी-कंटेनर सेवा-परत को कैसे पारित किया जा सकता है? (विभिन्न दृष्टिकोण भी बहुत स्वागत हैं।)

EDIT: यह उदाहरण देने के लिए एक उदाहरण है कि मैं जवाब और टिप्पणियों को कैसे समझता हूं।

मुझे सेवा लोकेटर (anti-)pattern से बचना चाहिए और इसके बजाय निर्भरता इंजेक्शन का उपयोग करना चाहिए। तो मान लें कि मैं नॉर्थविंड में उत्पादों और श्रेणियों के लिए एक व्यवस्थापक साइट बनाना चाहता हूं। मैं टेबल-परिभाषाओं के अनुसार मॉडल, भंडार, सेवाएं, नियंत्रक और विचार बनाते हैं। सेवाएं इस बिंदु पर सीधे भंडारों को कॉल करती हैं, वहां कोई तर्क नहीं होता है। मेरे पास कार्यक्षमता के खंभे हैं और विचार कच्चे डेटा दिखाते हैं। ये बाइंडिंग NinjectMVC3 के लिए कॉन्फ़िगर किया गया है:

private static void RegisterServices(IKernel kernel) 
    { 
     kernel.Bind<ICategoryRepository>().To<CategoryRepository>(); 
     kernel.Bind<IProductRepository>().To<ProductRepository>(); 
    }  

भंडार-उदाहरणों Ninject द्वारा बनाई गई हैं निर्माता इंजेक्शन की दो परतों के माध्यम से, ProductController में:

private readonly ProductsService _productsService; 
public ProductController(ProductsService productsService) 
{ 
    // Trimmed for this post: nullchecks with throw ArgumentNullException 
    _productsService = productsService; 
} 

और ProductsService:

protected readonly IProductRepository _productRepository; 
public ProductsService(IProductRepository productRepository) 
{ 
    _productRepository = productRepository; 
} 

मैं अब सेवाओं को रद्द करने की कोई ज़रूरत नहीं है लेकिन डीबी का मज़ाक उड़ाने के लिए तैयार है।
उत्पाद/संपादित में श्रेणियों की एक लटकती दिखाने के लिए मैं एक ViewModel कि उत्पाद के अलावा श्रेणियों धारण करना:

public class ProductViewModel 
{ 
    public Product Product { get; set; } 
    public IEnumerable<Category> Categories { get; set; } 
} 

ProductsService अब यह बनाने के लिए एक CategoriesRepository की जरूरत है।

private readonly ICategoryRepository _categoryRepository; 

    // Changed constructor to take the additional repository 
    public ProductsServiceEx(IProductRepository productRepository, 
     ICategoryRepository categoryRepository) 
    { 
     _productRepository = productRepository; 
     _categoryRepository = categoryRepository; 
    } 

    public ProductViewModel GetProductViewModel(int id) 
    { 
     return new ProductViewModel 
        { 
         Product = _productRepository.GetById(id), 
         Categories = _categoryRepository.GetAll().ToArray(), 
        }; 
    } 

मैं एक लटकती दिखाने के लिए return View(_productsService.GetProductViewModel(id)); और संपादित-व्यू के लिए मिलता संपादित कार्रवाई बदलने के लिए:

@model Northwind.BLL.ProductViewModel 
... 
    @Html.DropDownListFor(pvm => pvm.Product.CategoryId, Model.Categories 
     .Select(c => new SelectListItem{Text = c.Name, Value = c.Id.ToString(), Selected = c.Id == Model.Product.CategoryId})) 

एक छोटी सी समस्या इस के साथ, और कारण मैं सेवा लोकेटर के साथ भटक गया , यह है कि ProductController में अन्य क्रिया-विधियों में से कोई भी श्रेणियों-भंडार की आवश्यकता नहीं है। मुझे लगता है कि यह एक अपशिष्ट है और जब तक आवश्यक हो इसे बनाने के लिए तार्किक नहीं है। क्या मैं कुछ भूल रहा हूँ?

+1

संबंधित: http://stackoverflow.com/questions/2386487/is-it-better-to-create-a-singleton -टू-एक्सेस-एकता-कंटेनर-या-पास-इट-थ्रू-टी –

+0

धन्यवाद। मुझे एहसास नहीं हुआ कि मैंने सेवा लोकेटर का वर्णन किया है। – Grastveit

उत्तर

14

आप सभी Ninject सामान इस एक मैं सेटअप में इस

// global.aspx


protected void Application_Start() 
     { 
      // Hook our DI stuff when application starts 
      SetupDependencyInjection(); 
     } 

     public void SetupDependencyInjection() 
     {   
      // Tell ASP.NET MVC 3 to use our Ninject DI Container 
      DependencyResolver.SetResolver(new NinjectDependencyResolver(CreateKernel())); 
     } 

     protected IKernel CreateKernel() 
     { 
      var modules = new INinjectModule[] 
           { 
           new NhibernateModule(), 
           new ServiceModule(), 
           new RepoModule() 
           }; 

      return new StandardKernel(modules); 
     } 

तो जैसे कुछ कर सकते हैं चारों ओर तुम वस्तु पारित करने के लिए की जरूरत नहीं है। मैं अपने सभी बाध्यकारी को विभाजित करने के लिए 3 फाइलों के साथ एक कर्नल बना देता हूं ताकि यह ढूंढना आसान हो।


मेरी सेवा परत कक्षा में आप बस अपने इच्छित इंटरफेस में गुजरते हैं।यह सेवा वर्ग अपने स्वयं के प्रोजेक्ट फ़ोल्डर में है जहां मैं अपनी सभी सेवा परत कक्षाएं रखता हूं और इसमें निंजा लाइब्रेरी का कोई संदर्भ नहीं है।

// service.cs

private readonly IRepo repo; 
    // constructor 
     public Service(IRepo repo) 
     { 
      this.repo = repo; 
     } 

यह कैसे मेरे ServiceModule की तरह (क्या global.aspx में बन जाता है)

// ServiceModule() 
public class ServiceModule : NinjectModule 
    { 
     public override void Load() 
     { 

      Bind<IRepo>().To<Repo>(); 


     } 

    }  

इसे देख मैं करने के लिए इंटरफ़ेस कैसे बाँध लग रहा है रेपो अब जब भी यह इंटरफ़ेस दिखाई देता है तो यह स्वचालित रूप से रेपो क्लास को बांध देगा। तो आपको ऑब्जेक्ट को चारों ओर या किसी भी चीज़ को पास करने की आवश्यकता नहीं है।

आप अपनी सेवा परत में .dll आयात करने के बारे में चिंता की जरूरत नहीं है। मिसाल के तौर पर मेरे पास अपनी खुद की प्रोजेक्ट फ़ाइल में मेरी सेवा कक्षाएं हैं और जो कुछ भी आप ऊपर देखते हैं (पाठ्यक्रम की सेवा कक्षा की अपेक्षा करते हैं) मेरे वेबूई प्रोजेक्ट में है (जहां मेरे विचार और global.aspx है)।

Ninject परवाह नहीं करता है, तो सेवा एक अलग परियोजना में है के बाद से मुझे लगता है कि यह WebUI परियोजना में संदर्भित किया जा रहा है।

संपादित

आप NinjectDependecyResolver देने के लिए भूल

public class NinjectDependencyResolver : IDependencyResolver 
    { 
     private readonly IResolutionRoot resolutionRoot; 

     public NinjectDependencyResolver(IResolutionRoot kernel) 
     { 
      resolutionRoot = kernel; 
     } 

     public object GetService(Type serviceType) 
     { 
      return resolutionRoot.TryGet(serviceType); 
     } 

     public IEnumerable<object> GetServices(Type serviceType) 
     { 
      return resolutionRoot.GetAll(serviceType); 
     } 
    } 
+0

कन्स्ट्रक्टर इंजेक्शन और एमवीसी निर्भरता रीसोलवर के लिए +1। –

+0

बहुत ही गहन जवाब के लिए धन्यवाद! तो सेवाओं के अंदर इच्छाओं पर भंडार बनाने के बजाय या तो सुनिश्चित करें कि सेवा में सभी विधियां एक ही रिपॉजिटरीज़ का उपयोग करती हैं या अनियंत्रित भंडार बनाने के बारे में चिंता न करें? – Grastveit

+0

कृपया इस उत्तर से कस्टम निर्भरता रीसोलवर और एप्लिकेशन_स्टार्ट का उपयोग न करें। Ninject.MVC3 के साथ रहो! ऊपर वर्णित अनुसार कन्स्ट्रक्टर इंजेक्शन को बस कार्यान्वित करें। जैसा कि वर्णन किया गया है कि निनजेक्ट को सेवा लोकेटर के रूप में उपयोग करने की आवश्यकता नहीं है। –

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

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