Building a WinForms Application using MVC and Ninject as IoC Container - c#

I am having to re-write a large WinForms application and I want to use MVC to allow increased testing capability etc. I want to also adopt Ninject as my IoC container as it is lightweight, fast and will increase the exstensibility of my application going forward.
I have done a great deal of reading and I have managed to make a start on the arcitecture of this new application. However, I am not sure i have the right idea when using Ninject. The code...
Starting with Program.cs and related classes...
static class Program
{
[STAThread]
static void Main()
{
FileLogHandler fileLogHandler = new FileLogHandler(Utils.GetLogFilePath());
Log.LogHandler = fileLogHandler;
Log.Trace("Program.Main(): Logging initialized");
CompositionRoot.Initialize(new ApplicationModule());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(CompositionRoot.Resolve<ApplicationShellView>());
}
}
public class CompositionRoot
{
private static IKernel _ninjectKernel;
public static void Initialize(INinjectModule module)
{
_ninjectKernel = new StandardKernel(module);
}
public static T Resolve<T>()
{
return _ninjectKernel.Get<T>();
}
}
public class ApplicationModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IApplicationShellView)).To(typeof(ApplicationShellView));
}
}
An my ApplicationShellView is
public partial class ApplicationShellView : Form, IApplicationShellView
{
public ApplicationShellView()
{
InitializeComponent();
}
public void InitializeView()
{
dockPanel.Theme = vS2012LightTheme;
}
}
with interface
public interface IApplicationShellView
{
void InitializeView();
}
The controller for this view is
public class ApplicationShellController
{
private IApplicationShellView view;
public ApplicationShellController(IApplicationShellView view)
{
view.InitializeView();
}
}
Currently the controller is redundant, and although this code works and my view displays, I have some important questions...
Should I be using the ApplicationShellController to initialize my form, currently this is not using MVC "pattern"?
It feels like I have written a Service Locator, and from what I have read, this is bad. How else should I be using Ninject for IoC to initialize my application?
Any other advice as to what I am doing right[if anything!]/wrong?
Thanks very much for your time.

No you should not be initializing your controller, this exactly what IoC and Ninject are for. When you initialize your view/form, Ninject should make the view fetch the controller it depends on, which will auto fetch controllers it depends on and so on.
Of course this won't work like you've set it up right now. For starters, your view needs to know the controller it depends on.
public partial class ApplicationShellView : Form, IApplicationShellView
{
private IApplicationShellController _controller;
public ApplicationShellView()
{
InitializeComponent();
init();
//InitializeView()
}
private void init() {
_controller = NinjectProgram.Kernel.Get<IApplicationShellController>();
//Because your view knows the controller you can always pass himself as parameter or even use setter to inject
//For example: _controller.SetView1(this);
}
public void InitializeView()
{
dockPanel.Theme = vS2012LightTheme;
}
}
public class ApplicationShellController : IApplicationShellController
{
//Implementes functionality for the MainForm.
public ApplicationShellController()
{
//Also possible to add other controllers with DI
}
}
This does indeed look like a Service Locator, simply initializing your view should do be sufficient.
public class NinjectProgram
{
//Gets the inject kernal for the program.
public static IKernel Kernel { get; protected set; }
}
public class Program : NinjectProgram
{
[STAThread]
private static void Main()
{
Kernel = new StandardKernel();
Kernel.Load(new ApplicationModule());
Application.Run(new ApplicationShellView());
}
}
public class ApplicationModule : NinjectModule
{
public override void Load()
{
//Here is where we define what implementations map to what interfaces.
Bind<IApplicationShellController>().To<ApplicationShellController>();
//We can also load other modules this project depends on.
Kernel.Load(new NinjectModule());
}
}
Don't try and make it too complicated, a good start is important but you can always apply changes when and where needed during development.
I believe the following GitHub project might be a good starting point: Example of how you might use Ninject within a WinForms application.
If you have any more questions, just leave a comment and I'll try to answer them as soon as possible

Related

Adding singlton for every browser tab

I'm trying to implement web application and using a singleton object so I would be able to inject it to use it in other classes.
I want to open a new object every time the user opens a tab or similar in the browser. For example:
public class Singleton
{
public string Id{get;set;}
public Singleton(){Id=Guid.NewGuid().ToString();)
}
in startup:
services.AddSingleton<Singleton>(s=>new Singleton());
In some other class:
public class OtherClass{
private readonly Singleton singleton;
public OtherClass(Singleton singleton)
{
this.singleton = singleton;
}
}
The problem is that every tab has the same Id... I need a different id for every tab in the browser...
Thanks!
You have to make an Interface for the class you want to be a singleton. You register it in your Startup.cs as a Singleton
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISingleton, Singleton>();
}
You then proceed to inject the singleton interface into OtherClass
public class OtherClass{
private readonly Singleton singleton;
public OtherClass(ISingleton singleton)
{
this.singleton = singleton;
}
Hope this helps
Ok I've found some solution....
I'm creating a singleton class that has an object that will change ...
When I want to change the object details, I do this in a method...
Then I have the updated information for all the WebApp.
The change will be made in every method that I need to specify the object details...
For example:
public class InjectedSingleton
{
public MySession CurrentSession{get;set;}
public void SetSession(string sessionId)
{
CurrentSession = GetSessionById(sessionId);
}
public void NewSession()
{
CurrentSession = new MySession();
}
}
public class DoClass
{
private InjectedSingleton inj;
public DoClass(InjectedSingleton inj)
{
this.inj = inj;
}
public void OpenNewTab(string sessionId)
{
inj.SetSession(sessionId);
}
public void JustShowSomething()
{
Show(inj.CurrentSession.Id);
}
}
Now, the updated session is the required one, for everywhere in the app for the current user

Handling two different application flows

We are building an application where we have to have both old and new version to work side by side (V1 is old and V2 is new). Now to handle new flow we are using same old interfaces with everything being the same and differs only in functionality, hence now we have to define a named instance in-order to resolve the instances for new flow.
In the process teams have started using Service Factory Pattern as shown below
class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IServiceFactory serviceFactory)
{
_dataManager = serviceFactory.GetInstance<IDataManager>();
}
public void Execute()
{
_dataManager.Run();
}
}
Service Factory Class
public class ServiceFactory : IServiceFactory
{
private readonly IFeatureEvaluator _featureEvaluator;
public ServiceFactory(IFeatureEvaluator featureEvaluator)
{
_featureEvaluator = featureEvaluator;
}
public T GetInstance<T>()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
return ObjectFactory.GetInstance<T>("V2")
}
return ObjectFactory.GetInstance<T>();
}
}
Since Service Factory is anti-pattern and also it creates lot of complexities in retiring the old flow in future, I would want a way to initialize the dependencies at the container(structuremap ioc) itself or to work in a "Pure DI" way so that we can avoid headache. Any idea on how to tackle this.
Update:
IDataManager Implementation
public interface IDataManager
{
void Run();
}
public class OldFlow : IDataManager
{
public void Run()
{
//
}
}
public class NewFlow : IDataManager
{
public void Run()
{
//
}
}
IDataManager has 2 implementations and resolving the instance should be based on _featureEvaluator, if V2 flow then "newflow" should be instantiated else "old flow" instance
Why don't you just inject the dependency you need?
public class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IDataManager dataManager)
{
_dataManager = dataManager;
}
public void Execute()
{
_dataManager.Run();
}
}
In your Composition Root you can conditionally compose DataProcessor with the implementation of IDataManager you'd like:
public DataProcessor CreateDataProcessor()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
IDataManager dm = new NewFlow();
return new DataProcessor(dm);
}
IDataManager dm = new OldFlow();
return new DataProcessor(dm);
}
This seems to be similar to feature toggles. Why, by the way, is _featureEvaluator an interface? Wouldn't a bool suffice?

Fail to initialize dependencies. Singleton class using Dependency Injection (Ninject)

I want a singleton class that uses dependency injection (ninject) start as soon as the application starts. The singleton class resides in Domain layer(Class Library) -
Domain.Concrete.Operations. And I'm using this class in WebUI layer(MVC).
I'm stuck at initializing dependencies in static constructor of the service that I plan to start in Application_Start method. What is the right way to do it?
Singleton class:
namespace Domain.Concrete.Operations
{
public sealed class SingletonClass
{
private IInterface1 _iInterface1;
private IInterface2 _iInterface2;
public SingletonClass(IInterface1 iInterface1, IInterface2 iInterface2)
{
this._iInterface1 = iInterface1;
this._iInterface2 = iInterface2;
StartAllOperations();
}
public void StartAllOperations()
{
}
}
}
NinjectDependencyResolver:
namespace WebUI.Infrastructure
{
public class NinjectDependencyResolver : IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
{
kernel = kernelParam;
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
kernel.Bind<IInterface1>().To<Class1>();
kernel.Bind<IInterface2>().To<Class2>();
kernel.Bind<SingletonClass>().To<SingletonClass>().InSingletonScope();
}
}
}
As far as I understand this code will help to return the same instance of SigletonClass:
kernel.Bind<SingletonClass>().To<SingletonClass>().InSingletonScope();
Service in App_Start:
namespace WebUI.App_Start
{
public class OperationManagerService
{
private IInterface1 _iInterface1;
private IInterface2 _iInterface2;
static OperationManagerService() //static constructor cannot have parameters
{
_iInterface1 = //how to initialize
_iInterface2 = //interfaces here?
}
public static void RegisterService()
{
new SingletonClass(_iInterface1, _iInterface2);
}
}
}
Register service in Application_Start (Global.asax.cs):
namespace WebUI
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
OperationManagerService.RegisterService();
}
}
}
UPDATE:
I must admit that I'm able to initialize dependencies like this, but then I can only use the OperationManagerService class in controller. Not in Application_Start!
static OperationManagerService(IInterface1 iInterface1, IInterface2 iInterface2)
{
_iInterface1 = iInterface1;
_iInterface2 = iInterface2;
}
This leads me to thought that I can't use injection with Ninject in Application_Start. If it's true, then where is the right place to create a class that should load at startup?
You are trying to intermix the Singleton pattern with Ninject's Singleton Scope, which confuses who is trying to construct what when. Don't use the old the Singleton pattern when trying to use DI. Half of the point of DI is to manage the lifetime (scope) of the objects it contains. You do this by specifying .InSingletonScope() as you have done.
Now, onto your question of injecting dependencies into a startup feature: you will need to allow Ninject to construct the OperationManagerService in order to have the dependencies provided by Ninject. To do this, register it in Singleton scope, as you did with SingletonClass. The first time it is requested from the Ninject container, it will be constructed and injected with the necessary parameters. Singleton scope only tells Ninject to only ever construct one instance.
However, it seems that you would like it to be constructed during startup? If this is a requirement, something will need to ask for it. The simplest solution would be to get it after binding it:
private void AddBindings()
{
kernel.Bind<IInterface1>().To<Class1>();
kernel.Bind<IInterface2>().To<Class2>();
kernel.Bind<SingletonClass>().ToSelf().InSingletonScope();
kernel.Bind<OperationManagerService>().ToSelf().InSingletonScope();
kernel.Get<OperationManagerService>(); // activate
}
If you find yourself doing this alot, I have used a simple "auto-start" pattern:
public interface IAutoStart()
{
void Start();
}
public class SomeClassThatStarts : IAutoStart
{
public void Start()
{
Console.Log("Starting!");
}
}
public class AutoStartModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
foreach(var starter in Kernel.GetAll<IAutoStart>())
{
starter.Start();
}
}
}
Register the AutoStartModule last in your Kernel, and any IAutoStart will be loaded with any dependencies and started.

Database communication class as a singleton

Im considering, whether class which gonna communicate with database should be a singleton.
Instead of injecting context everywhere it's needed, I've created one inside Database class, which is the singleton class.
Is it good practice?
Code:
class DatabaseService
{
public FreelanceOrganizerDataContext DatabaseContext { get; private set; } = new FreelanceOrganizerDataContext();
static DatabaseService _singleton = new DatabaseService();
private DatabaseService() { }
public static DatabaseService GetDatabaseService()
{
return _singleton;
}
//Save Section
public void AddProject()
{
}
public void AddCustomer()
{
}
//etc
}
I would recommend using an IoC such as Unity or Autofac. You can do things such as Inject Dependecies into your classes, control the lifecycle of the objects (when and how often they are instantiated), and better set yourself up for Unit Tests.

In which library should an abstract factory interface and an actual factory be defined?

Short question
Where should I put the abstract factory interface and the actual factory?
Overview
I'm writing a simple video transcoding application and I'm trying to wrap my head around dependency injection.
I have separated my application into several projects in visual studio.
One class library for the transcoder, used by the application engine
One class library for the application engine that will be used by a gui or console interface
One console application that will be the main user interface for now
Without DI
This is what everything looks like before dependency injection
The transcoder lib:
namespace SimpleFFmpeg {
public interface ITranscoder {
void Transcode(String fileName);
}
public class Transcoder:ITranscoder {
// ...
public void Transcode(String fileName) {
// do transcoding stuff
}
// ...
}
}
The PusherEngine lib:
using SimpleFFmpeg;
namespace PusherLib {
public class PusherEngine {
private readonly List<VideoItem> _items;
public PusherEngine() {
_items = new List<VideoItem>();
}
// ...
public void processItems() {
foreach (VideoItem item in _items) {
ITranscoder t = new Transcoder();
t.Transcode(item.FileName);
}
}
// ...
}
}
The actual application:
namespace Pusher {
class Program {
static void Main(string[] args) {
PusherEngine pe = new PusherEngine();
pe.addVideoItem(new VideoItem(...));
pe.processItems();
}
}
}
Refactor to use DI
I create a generic abstract factory interface, like suggested in this question: Creating new instances while still using Dependency Injection
public interface IFactory<T> {
T Get();
}
Next I create a factory that creates ITranscoders
public class TranscoderFactory: IFactory<ITranscoder> {
public ITranscoder Get() {
return new SimpleFFmpeg.Transcoder();
}
}
Then I modify the PusherEngine to require a factory dependence in the constructor:
using SimpleFFmpeg;
namespace PusherLib {
public class PusherEngine {
private readonly IFactory<ITranscoder> _transcoderFactory;
private readonly List<VideoItem> _items;
public PusherEngine(IFactory<ITranscoder> transcoderFactory) {
_items = new List<VideoItem>();
_transcoderFactory = transcoderFactory;
}
// ...
public void processItems() {
foreach (VideoItem item in _items) {
ITranscoder t = _transcoderFactory.Get();
t.Transcode(item.FileName);
}
}
// ...
}
}
Finally, in the Program it looks like this:
namespace Pusher {
class Program {
static void Main(string[] args) {
IFactory<ITranscoder> f = new TranscoderFactory();
PusherEngine pe = new PusherEngine(f);
pe.addVideoItem(new VideoItem(...));
pe.processItems();
}
}
}
Question
In which lib/project should the IFactory interface be defined?
In which lib/project should the TranscoderFactory be defined?
Do they live in the Transcoder lib? In the PusherLib? Or in the actual frontend application?
I'm looking for best practices.
Thanks!
In my opinion, it doesn't matter. For me, the main point of dependency injection is being able to inject something other than the real implementation while testing. I keep my unit tests in a separate project along with the various mock definitions used for testing. The real implementations as well as the 'abstract' logic are all kept in the same assembly/project/namespace.
If you really need a factory (see comment), then this blog post by Mark Seemann addresses this issue.
Briefly, if you use the IoC Container in your factory, you want to use it in the composition root. If not, there is no harm for it to remain in the same assembly as the class it is instantiating.
EDIT
For your particular case, you do not need a factory, since you already have everything you need to solve this dependency.
using SimpleFFmpeg;
namespace PusherLib {
public class PusherEngine {
private readonly ITranscoder _transcoder;
private readonly List<VideoItem> _items;
public PusherEngine(ITranscoder transcoder) {
_items = new List<VideoItem>();
_transcoder = transcoder;
}
// ...
public void processItems() {
foreach (VideoItem item in _items) {
_transcoder.Transcode(item.FileName);
}
}
// ...
}
}
The initialization would then look like this:
namespace Pusher {
class Program {
static void Main(string[] args) {
ITranscoder t = new Transcoder();
PusherEngine pe = new PusherEngine(t);
pe.addVideoItem(new VideoItem(...));
pe.processItems();
}
}
}
The reason why a factory was needed in the answer you linked is that the dependency needed values only known at run-time to be able to be instantiated, while your dependency does not require run-time dependent arguments to be created.
To answer your actual question, and not if this is a good use case for a factory or not:
For this purpose I sometimes split up Interface and Implementation into different projects, and something like your IFactory<> would live in the Common.I project.
This doesn't work in every scenario, but one of the advantages of this approach for me is that I can swap out Implementation dll's with either mocks or a new implementation when there are underlying technology changes.
For example, we recently switched from parsing xml files from a directory to getting data from a service. The only thing I had to update on client machines was this one Implementation dll because the interface did not change at all.
But I guess in the end it doesn't really matter, as mentioned before.

Categories

Resources