6
public class StatisticsViewPresenter 
{ 
    private IStatisticsView view; 
    private Statistics statsModel; 

    public StatisticsViewPresenter(IStatisticsView view, Statistics statsModel) 
    { 
     this.view = view; 
     this.statsModel = statsModel; 
    } 
} 

मैं घटनाओं का उपयोग नहीं करते (लेकिन अगर यह मेरी समस्या का समाधान कर सकते हैं के लिए तैयार हूँ), तो मेरे देखें कक्षाएं इस तरह दिखेगा:डिज़ाइनर को खुश रखते हुए उपयोगकर्ता नियंत्रण विचारों पर निर्भरता इंजेक्शन कैसे लागू करें?

public class StatisticsForm : Form, IStatisticsView 
{ 
    public StatisticsForm() 
    { 
     InitializeComponent(); 
    } 

    [Inject] 
    public StatisticsViewPresenter Presenter 
    { 
     private get; 
     set; 
    } 
} 

साथ

kernel.Bind<StatisticsPresenter>().ToSelf().InSingletonScope(); 
kernel.Bind<IStatisticsView>().To<StatisticsForm>(); 
kernel.Get<IStatisticsView>(); 

यह बनाता है प्रपत्र, प्रस्तुतकर्ता बनाता है, फिर प्रेजेंटर प्रॉपर्टी में प्रस्तुतकर्ता को इंजेक्ट करता है। सब कुछ peachy। (उस सिंगलटन-स्कोप्ड प्रेजेंटर के अलावा - ऐसा करने के बेहतर तरीके से कोई विचार? शायद प्रस्तुतकर्ता के प्रस्तुतकर्ता के अंदर प्रस्तुतकर्ता की प्रस्तुति प्रॉपर्टी में प्रस्तुतकर्ता को मैन्युअल रूप से इंजेक्ट करें: this.view.Presenter = this)।

लेकिन अगर मैं सांख्यिकीफॉर्म नियंत्रण में सांख्यिकीफॉर्म को चालू करता हूं और इसे अपने मेनफॉर्म पर खींचता हूं, तो इसे निनजेक्ट द्वारा मेनफॉर्म में इंजेक्शन नहीं दिया जा रहा है, यह केवल डिजाइनर द्वारा नया किया जा रहा है। मैं यहां तीन समाधान देखता हूं:

1) UserControls का उपयोग न करें और केवल एक विशाल रूप का उपयोग करें जो इन एकाधिक विचारों को लागू करता है (eww);

2) मेरे फॉर्म में UserControls इंजेक्ट करें और डिज़ाइनर समर्थन खो दें;

3) आपका समाधान! :)

+1

अंतिम समाधान क्या था? मैं डिजाइनर में UserControls का उपयोग करने और निर्भरता इंजेक्शन का उपयोग करने का एक तरीका भी ढूंढ रहा हूं। – Nathan

+0

कृपया हमें बताएं कि क्या आपको एक व्यवहार्य समाधान मिला है। धन्यवाद! –

+0

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

उत्तर

2

यह निश्चित रूप से एक दिलचस्प क्षेत्र है, क्या मुझे कहना चाहिए, अनुसंधान करना चाहिए। हमने खुद को एक समाधान बनाया है जहां हम एक सामान्य रूप में उपयोगकर्ता नियंत्रण होस्ट करते हैं।

हमारा सामान्य रूप डिज़ाइनर के उपयोग के लिए नहीं है। कोड के माध्यम से हम चयनित उपयोगकर्ता नियंत्रण को गतिशील रूप से फॉर्म में जोड़ते हैं।

अन्य ढांचे के लिए आपको माइक्रोसॉफ्ट पैटर्न & प्रथाओं समूह से Prism/Composite पर देखना चाहिए। Here's an article WinForms के लिए एक्सटेंशन पर चर्चा।

2

रूपों, usercontrols और डिजाइनर के साथ Ninject उपयोग करने के लिए मेरे दृष्टिकोण है:

  • कारखानों का उपयोग करें (usercontrols के लिए भी अगर आप dinamically कुछ नियंत्रण बनाने) रूपों बनाने के लिए
  • usercontrols के लिए
  • और प्रपत्र रचनाकारों को पैरामीटर के बिना रखता है और संपत्ति इंजेक्शन का उपयोग करता है
  • कर्नेल में Activation strategy जोड़ें जो जांचता है कि निंजेक्ट ने अभी कोई फ़ॉर्म या उपयोगकर्ता नियंत्रण बनाया है या नहीं। यदि ऐसा है, तो सक्रियण रणनीति UserControl (या प्रपत्र) की नियंत्रण संपत्ति में नियंत्रणों पर पुनरावृत्ति करती है और प्रत्येक उपयोगकर्ता नियंत्रण के लिए कर्नेल.इजेक्ट (UserControl) को कॉल करती है।

आप डिजाइनर का उपयोग करें और रूपों और Ninject के माध्यम से इंजेक्शन निर्भरता के साथ usercontrols हो सकता है (एक सक्रियण रणनीति कुछ कोड Ninject यह एक वस्तु इंजेक्शन के बाद निष्पादित करता है)।

केवल दोष यह है आप usercontrols (और रूपों)

namespace Majiic.Ninject 
{ 
public class WindowsFormsStrategy : ActivationStrategy 
{ 
    // Activate is called after Kernel.Inject 
    //even for objects not created by Ninject 
    //To avoid multiple "injections" in the same nested controls 
    //we put this flag to false. 
    private bool _activatingControls = false; 
    public override void Activate(IContext context, InstanceReference reference) 
    { 
     reference.IfInstanceIs<UserControl>(uc => 
     { 
      if (!_activatingControls) 
      { 
       Trace.TraceInformation("Activate. Injecting dependencies in User control of type {0}", uc.GetType()); 
       _activatingControls = true; 
       context.Kernel.InjectDescendantOf(uc); 
       _activatingControls = false; 
      } 
     }); 
     reference.IfInstanceIs<Form>(form => 
     { 
      if (!_activatingControls) 
      { 
       Trace.TraceInformation("Activate. Injecting dependencies in Form of type {0}", form.GetType()); 
       _activatingControls = true; 
       context.Kernel.InjectDescendantOf(form); 
       _activatingControls = false; 
      } 
     }); 
    } 


} 
} 

गिरी बनाएँ और जोड़ने के लिए निर्माता इंजेक्शन के बजाय संपत्ति इंजेक्शन का उपयोग करने के सक्रियण रणनीति

var kernel=new StandardKernel(new CommonMajiicNinjectModule()); 
kernel.Components.Add<IActivationStrategy, WindowsFormsStrategy>(); 

गिरी है है अवरोधकों पर नियंत्रण करने के लिए एक्सटेंशन

namespace Majiic.Ninject 
{ 
static public class WinFormsInstanceProviderAux 
{ 
    static public void InjectDescendantOf(this IKernel kernel, ContainerControl containerControl) 
    { 
     var childrenControls = containerControl.Controls.Cast<Control>(); 
     foreach (var control in childrenControls) 
     { 
      InjectUserControlsOf(kernel, control); 
     } 
    } 

    static private void InjectUserControlsOf(this IKernel kernel, Control control) 
    { 
     //only user controls can have properties defined as n-inject-able 
     if (control is UserControl) 
     { 
      Trace.TraceInformation("Injecting dependencies in User Control of type {0}", control.GetType()); 
      kernel.Inject(control); 
     } 
     //A non user control can have children that are user controls and should be n-injected 
     var childrenControls = control.Controls.Cast<Control>(); 
     foreach (var childControl in childrenControls) 
     { 
      InjectUserControlsOf(kernel, childControl); 
     } 
    } 
} 
} 
1

मैं आर इंजेक्ट करने के लिए निर्भरता की आवश्यकता के साथ कुछ पुन: प्रयोज्य UserControls बनाया। IoC Container का उपयोग उन UserControl एस बनाने के लिए नहीं किया जाता है, जाहिर है कि वह निर्भरता को स्वचालित रूप से इंजेक्ट नहीं कर सकता है।

मेरा समाधान कम से कम संपत्ति इंजेक्शन सक्षम करने के लिए एक बेस-क्लास है। कन्स्ट्रक्टर इंजेक्शन समर्थित नहीं है, क्योंकि पैरामीटर रहित कन्स्ट्रक्टर का उपयोग उन उदाहरणों को बनाने के लिए किया जाता है।

public class NinjectUserControl : UserControl 
{ 

    // Generally this is considered to be a bad practice, 
    //however I didn't find any better way. If you do, please share :) 
    public static IKernel Kernel { private get; set; } 

    protected override void OnInitialized(EventArgs e) 
    { 
     base.OnInitialized(e); 
     RequestActivation(Kernel); 
    } 

    protected virtual void RequestActivation(IKernel kernel) 
    { 
     kernel?.Inject(this); 
    } 
} 

इसे काम करने के लिए आपको कर्नेल को एक बार सेट करने की आवश्यकता है। आम तौर पर यह अपने program.cs (WinForms) के अंदर कहीं न कहीं है या App.xaml.cs (WPF)

IocKernel = new StandardKernel(); // typically a static member 
NinjectUserControl.Kernel = IocKernel; 
IocKernel.Load(new Module()); // loading modules 
// .. Create MainForm or whatever 

का उपयोग करने के लिए बस NinjectUserControl वारिस और फिर कर्नेल संपत्ति इंजेक्शन के माध्यम से अपने निर्भरता सम्मिलित करें करते हैं:

[Inject] 
public IService Service { private get; set; } 

कृपया ध्यान दें, कि उन निर्भरताओं को कन्स्ट्रक्टर के अंदर सुलभ नहीं है।

+0

ध्यान दें कि इस समाधान को लागू करने के लिए उपयोग किए जाने वाले फ्रेमवर्क 'WPF' है, हालांकि यह' WinForms 'का उपयोग करके बहुत समान काम करना चाहिए – LuckyLikey

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