I need to auto-resolve dependencies of my windows form. The only problem is my forms constructor expects an integer value as well. Please have a look at the implementation in the code section.
//Ninject bindings
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<LogToDB>();
Bind<ICopy>().To<CopyToFolder>();
}
}
//WinForm - Form1
public partial class Form1 : Form
{
public readonly ILogger _processRepository;
public readonly Icopy _copy;
public readonly int ValueToEdit;
public Form1(int valueToEdit, ILogger logger, ICopy copy)
{
this._processRepository = logger;
this._copy = copy;
this.ValueToEdit = valueToEdit;
InitializeComponent();
}
}
//main
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
IKernel kernel = new StandardKernel(new Bindings());
Application.Run(kernel.Get<Form1>());
}
I get an error:
Ninject.ActivationException: 'Error activating int
No matching bindings are available, and the type is not self-bindable.
How can I auto resolve the form dependencies and also be able to pass the integer value? Actually, I have used the same form for add and edit purpose so while editing, this edit value should be set.
I guess the cleanest way to solve this problem is to create a factory:
interface IForm1Factory
{
Form1 Create(int valueToEdit);
}
class Form1Factory
{
public readonly ILogger _processRepository;
public readonly Icopy _copy;
public Form1Factory(ILogger logger, ICopy copy)
{
this._processRepository = logger;
this._copy = copy;
}
public Form1 Create(int valueToEdit)
{
return new Form1(valueToEdit, _processRepository, _copy);
}
}
There is also an extension (Ninject.Extensions.Factory) that allow you to auto-generate factories such as the Form1Factory based on the interface. If you use that extension, you declare that using Bind<IForm1Factory>().ToFactory().
using Ninject;
using Ninject.Modules;
using Ninject.Parameters;
//Add new class
public class CompositionRoot
{
public static IKernel _ninjectKernel;
public static void Wire(INinjectModule module)
{
_ninjectKernel = new StandardKernel(module);
}
public static T Resolve<T>()
{
return _ninjectKernel.Get<T>();
}
public static T ResolveWithArgument<T>(ConstructorArgument argument)
{
return _ninjectKernel.Get<T>(argument);
}
}
//Ninject bindings
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<LogToDB>();
Bind<ICopy>().To<CopyToFolder>();
}
}
//WinForm - Form1
public partial class Form1 : Form
{
public readonly ILogger _processRepository;
public readonly Icopy _copy;
public readonly int ValueToEdit;
public Form1(ILogger logger, ICopy copy, int valueToEdit)
{
this._processRepository = logger;
this._copy = copy;
this.ValueToEdit = valueToEdit;
InitializeComponent();
}
}
//main
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
//Apply the binding rule first
CompositionRoot.Wire(new Bindings());
//Then resolve your form dependencies this way using Ninject passing along the
constructor arguments.
CompositionRoot.ResolveWithArgument<Form1>(new ConstructorArgument("valueToEdit",
1)).ShowDialog();
}
Related
I have created one method in a controller, but I need to call this method into anther class and I don't know how to call it.
my sample code :-
public class ReportController : BaseController
{
private readonly IPermissionService _permissionService;
private readonly ICompaniesService _companyService;
public ReportController(IPermissionService permissionService,
ICompaniesService companyService)
{
this._permissionService = permissionService;
this._companyService = companyService;
}
public void Reporting()
{
// code
}
}
public class Home {
public void Execute()
{
//I need to execute the Reporting method here
}
}
I have tried many things to call my method in another class method but I can't get it to work.
It's a bad design way to have some code in a controller who have to be called in several places. Create a class in your project or in an external DLL who contains this code and call this class in the controllers who need this method.
Create a class somewhere (in you project, or in a class library) :
public class MyClass
{
public MyClass()
{}
public void MyMethod()
{
// Some code here
}
}
And implement this code in your controllers or classes who need this.
public class ReportController : BaseController
{
private readonly IPermissionService _permissionService;
private readonly ICompaniesService _companyService;
public ReportController(IPermissionService permissionService,
ICompaniesService companyService)
{
this._permissionService = permissionService;
this._companyService = companyService;
}
public void Reporting()
{
MyClass myClass = new MyClass();
myClass.MyMethod();
}
}
By the way, if your code doesn't need any instance, you can create a static class, like :
public static class MyClass
{
public static void MyMethod()
{
// Some code here
}
}
public class ReportController : BaseController
{
private readonly IPermissionService _permissionService;
private readonly ICompaniesService _companyService;
public ReportController(IPermissionService permissionService,
ICompaniesService companyService)
{
this._permissionService = permissionService;
this._companyService = companyService;
}
public void Reporting()
{
MyClass.MyMethod();
}
}
There are two ways of accomplishing this. You are using dependency injection in your controller's constructor, so you have two options of doing this (not sure if I have missed any?):
Create an instance of each of your services in the calling method and pass these instances through when instantiating the controller, or
Add a constructor to your home class, set the services and pass them through when instantiating the controller
Option 1:
public class Home
{
public void Execute()
{
// Create the variables that are needed by the constructor
IPermissionService permissionService = new PermissionService();
ICompaniesService companiesService = new CompaniesService();
// Create an instance of your controller and pass through
// the variables created above
ReportController reportController = new ReportController(permissionService, companiesService);
// Now that you have an instance of your controller call the method
reportController.Reporting();
}
}
It works on the same principle as creating an instance of a class and then calling its methods.
Option 2:
public class Home
{
private IPermissionService permissionService;
private ICompaniesService companiesService;
public Home(IPermissionService permissionService, ICompaniesService companiesService)
{
this.permissionService = permissionService;
this.companiesService = companiesService;
}
public void Execute()
{
ReportController reportController = new ReportController(permissionService, companiesService);
reportController.Reporting();
}
}
ReportController reportController = new ReportController();
reportController.Reporting();
As you would any other class that's method isn't static
Please read this answer, they go into a lot more detail than I do
How to inject dependency into CompositeControl?
I tried the following approach - MyServerControl's Calculate is still null.
Thanks!
public class MyServerControl : CompositeControl
{
private TextBox TextBox1;
private TextBox TextBox2;
private Label Label1;
[Inject] // **** This is null ****
public ICalculate Calculate { get; set; }
protected override void CreateChildControls()
{
TextBox1 = new TextBox {ID = "TextBox1", Text = "1"};
Controls.Add(TextBox1);
TextBox2 = new TextBox {ID = "TextBox2", Text = "2"};
Controls.Add(TextBox2);
var button1 = new Button {ID = "Button1", Text = "Calculate"};
button1.Click += button1_Click;
Controls.Add(button1);
Label1 = new Label {ID = "Label1"};
Controls.Add(Label1);
}
private void button1_Click(object sender, EventArgs e)
{
int value1 = Int32.Parse(TextBox1.Text);
int value2 = Int32.Parse(TextBox2.Text);
Label1.Text = "Result:" + Calculate.Add(value1, value2);
}
}
public interface ICalculate
{
int Add(int x, int y);
}
public class Calculate : ICalculate
{
public int Add(int x, int y)
{
return x + y;
}
}
Default Ninject.Web.Common Bootstrapper from NuGet:
using System.Net.NetworkInformation;
[assembly: WebActivator.PreApplicationStartMethod(typeof(NinjectDemo.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(NinjectDemo.App_Start.NinjectWebCommon), "Stop")]
namespace NinjectDemo.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
IKernel kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICalculate>().To<Calculate>().InSingletonScope();
}
}
}
Updated:
I'm not able to get instance to kernel in Page_Load. Am I missing something?
<my:MyServerControl ID="MyServerControl1" runat="server" />
public partial class Default : Page
{
[Inject]
public ICalculate _calculate { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
kernel.Inject(MyServerControl1); // kernel is not available
}
}
I think you could just use the feature that satisfies dependencies on an existing object. In this particular case, in any context your control is used, you just call
kernel.Inject( myControl );
where myControl is an existing instance of your composite control. This has to be called from the code behind, somewhere in the pipeline where the instance is already created. Page_Load would most probably be fine.
Edit: there are numerous ways to be able to resolve anywhere in your application. You could for example have a global service locator. But since you are using the Bootstrapper, you should be able to resolvd your kernel anywhere
var kernel = (IKernel)Bootstrapper.Container;
Your Default page doesn't know about NinjectWebCommon class existence. It also cannot know about the kernel variable which is a NinjectWebCommon.CreateKernel() method's member. The simplest solution is the following:
public static class NinjectWebCommon
{
...
private static IKernel kernel;
public static IKernel CreateKernel()
{
if(kernel != null)
return kernel;
kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
...
}
public partial class Default : Page
{
[Inject]
public ICalculate _calculate { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
NinjectWebCommon.CreateKernel().Inject(MyServerControl1);
}
}
The other way would be to use Ninject magic. Your application class would probably need to inherit from a class provided by Ninject. In MVC it's a NinjectHttpApplication class, which overrides the bootstrapper. Than you could probably go with Wiktor's answer.
Honestly I don't like that Ninject magic, as it sometimes doesn't work for me and than it's very hard to find out why. In my MVC application I ended up creating my own ConfrollerFactory, which injected the dependencies explicitly. It also may be a pain if you want to change your IOC container.
you need to register your Ioc config, see example:
public static void RegisterIoc(HttpConfiguration config)
{
var kernel = new StandardKernel(); // Ninject IoC
kernel.Bind<IMyService>().To<MyService>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
Add this class in your App_start folder, and then write in Global.asax.cs:
// Tell WebApi to use our custom Ioc (Ninject)
IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
Below Class2 has a property that needs to be set before GetSomething is called, however because I access Class2 at the top of Class1 the property is always null when it gets to Something class. I can't seem to figure out how to change my code to set the property before it's used. Anyone?
EDIT
I want to pass the dependency from form1's constructor, not hardcode it further up the chain.
public partial class form1
{
private static readonly ISomeConstructedClass someConstructedClass = Class1.SomeConstructedClass;
public form1()
{
someConstructedClass.SomeDependency = new SomeDependency();
someConstructedClass.Whatever();
}
}
public static class Class1
{
public static readonly ISomething something = (ISomething)Class2.GetSomething("something");
public static ISomeConstructedClass SomeConstructedClass
{
get
{
return something.SomeConstructedClass;
}
}
}
....
}
public class Class2
{
public static ISomeDependency SomeDependency
{
get;
set;
}
public static GetSomething(string something)
{
switch(something)
{
case "something":
return new Something( SomeDependency );
}
}
}
public class Something : ISomething
{
public ISomeDependency SomeDependency
{
get;
set;
}
public Something(ISomeDependency someDependency)
{
SomeDependency = someDependency;
}
}
[Re]Edit:
I was confused about what you were trying to do before, you just need to create the dependency first.
public partial class form1
{
private static /*readonly*/ ISomeConstructedClass someConstructedClass;
public form1()
{
Class2.SomeDependency = new SomeDependency();
someConstructedClass = Class1.SomeConstructedClass;
someConstructedClass.Whatever();
}
}
I would also move the creation of something into the property just to make sure it is not initialized too soon (before the form1 constructor is called).
public static class Class1
{
public static ISomething something;
public static ISomeConstructedClass SomeConstructedClass
{
get
{
if (something == null) {
something = (ISomething)Class2.GetSomething("something");
}
return something.SomeConstructedClass;
}
}
}
You can use a static constructor. This is called before any static (or instance for that matter) fields or methods are called/accessed.
Something like:
static Class2() {
SomeDependency = SomeDependencyYouNeed;
}
Why are you using static methods? It looks like you're attempting a sort of Dependency Injection. Either create an instance of Class2 and pass the dependency in the constructor (and don't use static methods), or pass the dependency as a parameter of the GetSomething() method.
public static GetSomething(string something, ISomeDependency dependency).
I'm trying to put config data from host to plugins but I always get nulls at plugins. My code responsible for plugins is below:
Form:
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
DataStorage.Instance.LoadModes();
DataStorage.Instance.ActiveMode = "aaa";
DataStorage.Instance.RulesFile = "bbb";
DataStorage.Instance.SetProjectName("cccc");
DataStorage.Instance.LoadRules();
DataStorage.Instance.LoadPlugins();
}
}
DataStorage:
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(ConfigStorage))]
public class DataStorage: ConfigStorage
{
//fields and properties here
public string ActiveMode;
[ImportMany(typeof (IAPlugin))]
public IEnumerable<Lazy<IAPlugin, IAPluginData>> aPlugins;
[ImportMany(typeof (IBPlugin))]
public IEnumerable<Lazy<IBPlugin, IBPluginData>> bPlugins;
private CompositionContainer _container;
private static readonly DataStorage instance = new DataStorage();
static DataStorage()
{
}
private DataStorage()
{
Init();
}
public static DataStorage Instance
{
get { return instance; }
}
private void Init()
{
//code here
}
public void LoadPlugins()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(ConfigStorage).Assembly));
catalog.Catalogs.Add(new DirectoryCatalog(Settings.Default.GetPathFor("Plugins")));
_container = new CompositionContainer(catalog);
try
{
_container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
}
ConfigStorage:
public abstract class ConfigStorage
{
public string RulesFile;
public string ActiveMode;
//properties and methods
}
Plugin:
[Export(typeof (IAPlugin))]
[ExportMetadata("Name", "myNameIsBond")]
public class myNameIsBond : IAPlugin
{
protected readonly ConfigStorage configStorage;
[ImportingConstructor]
public myNameIsBond (ConfigStorage configStorage)
{
if (configStorage == null)
throw new ArgumentNullException("configStorage");
this.configStorage = configStorage;
}
public string DoStep(string url)
{
Console.WriteLine(configStorage.ActiveMode); //this is null - it should be "aaa"
return url;
}
}
When I run plugin.Value.DoStep("sth"); the Console.WriteLine(configStorage.ActiveMode); always print null - when I debugging: all fields from configStorage are nulls. What I'm doing wrong? How can I put DataStorage instance to my plugins?
I think the problem is that the ConfigStorage export is showing up in the catalog, so the imports are getting satisfied with a version created by the catalog instead of the singleton you have configured. Try putting a PartNotDiscoverableAttribute on the DataStorage class.
As an aside, your DataStorage constructor is private, but it looks like the catalog can still create a separate version of it because the constructor is invoked through reflection.
I typically don't use an instance variable at all and just let MEF create the singleton, but if you really want to have an instance property you can do something like
// note that there is no export attribute here
public class DataStorage: ConfigStorage
{
[Export(typeof(ConfigStorage))]
public static DataStorage instance { get; private set; }
}
So that MEF will export your singleton instance rather than creating a new object.
This is how I understand I can implement the singleton pattern in C#:
public class ChesneyHawkes{
private static ChesneyHawkes _instance = new ChesneyHawkes();
public ChesneyHawkes Instance {get{return _instance;}}
private ChesneyHawkes()
{
}
}
What if I want to provide a single instance of an object, so that there can only ever be one, make the access to it public, but only allow it to be created or replaced by another singleton.
// The PuppetMaster should be the only class that
// can create the only existing Puppet instance.
public class PuppetMaster{
private static PuppetMaster_instance = new PuppetMaster();
public static PuppetMaster Instance {get{return _instance;}}
// Like a singleton but can be replaced at the whim of PuppetMaster.Instance
public static Puppet PuppetInstance {get {return Puppet;}}
private PuppetMaster()
{
}
public class Puppet{
// Please excuse the pseudo-access-modifier
puppetmasteronly Puppet(){
}
}
}
// To be accessed like so.
PuppetMaster.Puppet puppet = PuppetMaster.Instance.PuppetInstance;
You don't really need more than one singleton for that. Look at this example:
using System;
// interface for the "inner singleton"
interface IPuppet {
void DoSomething();
}
class MasterOfPuppets {
// private class: only MasterOfPuppets can create
private class PuppetImpl : IPuppet {
public void DoSomething() {
}
}
static MasterOfPuppets _instance = new MasterOfPuppets();
public static MasterOfPuppets Instance {
get { return _instance; }
}
// private set accessor: only MasterOfPuppets can replace instance
public IPuppet Puppet {
get;
private set;
}
}
class Program {
public static void Main(params string[] args) {
// access singleton and then inner instance
MasterOfPuppets.Instance.Puppet.DoSomething();
}
}