Ninject ActivationException in WinForms application - winforms

I am working on a project to implement DI (using Ninject) into an existing WinForms application, however I have hit a few issues and my knowledge of working with DI in WinForms is limited at best, however I have successfully used it several times in MVC projects.
I get this message when trying to create a form that has a constructor that requires an interface of a repository:
Error activating IProductionRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IProductionRepository into parameter
productionRepository of constructor of type Main
1) Request for Main
I have searched on the web, but most of the articles I have read on this error either a dealing with much more complicated setups or are regarding parameter injection, which I am not sure is the issue here.
I have a form that is to launch the form that is to use DI (the error occurs on the kernel.Get call:
Private Sub txt_Click(sender As System.Object, e As System.EventArgs) Handles txt.Click
Try
Dim kernel As Ninject.IKernel =
New Ninject.StandardKernel(New NinjectFactory())
Dim form As Main = kernel.Get(Of Main)()
form.ConnectionString = App.pstrConnectString
form.ShowDialog(Me)
Catch ex As Exception
Support.ErrorHandler.ReportError(ex.Message, ex, True)
End Try
End Sub
I have my NinjectFactory with the correct binding (and several other commented out attempts):
public class NinjectFactory : NinjectModule
{
private IKernel _ninjectKernel;
public NinjectFactory()
{
_ninjectKernel = new StandardKernel();
}
public override void Load()
{
//_ninjectKernel.Bind(typeof(IRepository<>))
// .To(typeof(GenericRepository<>));
//_ninjectKernel.Bind(typeof(IProductionRepository))
// .To(typeof(ProductionRepository));
_ninjectKernel.Bind<IProductionRepository>().To<ProductionRepository>();
}
}
Finally I have the form I am trying to launch:
private IProductionRepository _productionRepository;
public string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
}
[Inject]
public Main(IProductionRepository productionRepository) : this()
{
this._productionRepository = productionRepository;
}
public Main()
{
InitializeComponent();
}
This is how I have used Ninject in MVC projects before and I haven't had an issue, however obviously there is something different regarding WinForms.
Any help would be greatly appreciated.

I suggest to use single point of dependency resolution, know as Composition Root, suggested by Mark Seemann (#mark-seemann) in his great book Dependency Injection in .NET. Your CompositionRoot might look like this:
public class CompositionRoot
{
private static IKernel _ninjectKernel;
public static void Wire(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(IRepository<>)).To(typeof(GenericRepository<>));
}
}
You can wire them in Program
CompositionRoot.Wire(new ApplicationModule());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(CompositionRoot.Resolve<Form1>());
Now your button handler could look like this:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(_productionRepository.ToString());
}
Note: if you want to test your application with different dependencies, which is probably the case, then you create another module with different wiring configuration. In tests you will have another wiring logic with stubs and mocks.
I also don't like NInject attributes on my model and if you use constructor injection - you can get rid of them. My entities are simple POCOs.
public interface IProductionRepository
{
}
public class ProductionRepository : IProductionRepository
{
public override string ToString()
{
return "Foo";
}
}
Mark also makes a great case for WinForms with DI pattern and how it can be implemented, i really suggest his book.

Related

Using a generic ViewModel

I have a WPF MVVM App, but I want my ViewModel to be generic. What the app is suppose to do is take some Data and do CRUD operations on it without knowing the Type of the data it's getting at the compile-time. So I declared my ViewModel like this:
public class GenericViewModel<T> where T : class
{
private void ConstructorBase()
{
Type theType = typeof(T);
Properties = theType.GetProperties().ToList();
}
public GenericViewModel(DbContext _dbContextInsert) //pravi novi repository na osnovu DbContexta
{
ConstructorBase();
_R = new RepositoryGlobal<T>(_dbContextInsert);
}
public T newT { get; set; }
public T selectedT { get; set; }
public List<PropertyInfo> Properties { get; set; }
private RepositoryGlobal<T> _R;
}
Now, disregard almost everything you see inside it, the only important thing is that the Constructor is never reached. I set this ViewModel as the DataContext for the main window like this:
InitializeComponent();
this.DataContext = new GenericViewModel<Person>(new PersonDbContext());
But when I put a breakpoint inside the ViewModel's constructor, the program never gets stopped.
Any ideas?
Dependencies should be abstractions, not implementations.
Your generic view model should not create it's own repository, instead you should pass in an instance of this dependency via the constructor.
public class GenericViewModel<T> where T : class
{
protected readonly IRepository<T> _Repository;
public GenericViewModel(IRepository<T> repository)
{
_Repository = repository;
}
...
}
You would then create an instance of your repository like so:
DbContext context = new PersonDbContext();
IRepository<Person> personRepo = new PersonRepository(context);
GenericViewModel<Person> personViewModel = new GenericViewModel<Person>(personRepo);
There, your View Model's dependencies are no longer tied to a specific implementation, your code is now far more adaptable to changes. Not to mention massively easier to test.

WPF/MVVM navigation with direct ViewModel switching

I've started writing my first WPF/MVVM and as many other people have found, dealing with navigation between views is rather confusing.
I've been searching for a while and most of the topics either recommend using MVVM Light/PRISM, or come up with solutions similar to one from here.
I'm trying to approach an MVVM navigation mechanism in which I can switch directly from one view to another view (without using the datatemplate switch from the parent window). Let's say, I have an app with a main window loading dynamic content from different usercontrols (views).
The MainWindowViewModel would have a CurrentV property pointed to, say, UserListV and a CurrentVM property pointed to UserListVM. Now that I select one user from the list and click on the View button to view that user details in another screen of the same window. This should allow me to switch to the UserV with UserVM as data context.
I wonder how should I, while being on UserListVM, make a call to MainWindowViewModel to update the CurrentV and CurrentVM values, and switching the window to the UserV accordingly?
Any suggestion of a better idea is more than welcome!
Thank you very much!
I use a messaging service for communication between ViewModels, while still keeping them decoupled. If you are using MVVMLight, it comes with one. I prefer not to use an MVVM framework, and write my own messaging service. Here is an example of one from a recent project:
public class MessageService : IMessageService
{
private List<IMessageSubscription> subscribers; //list of subscription objects registered
public MessageService()
{
subscribers = new List<IMessageSubscription>();
}
public void Subscribe<T>(string message, Action<T> action)
{
subscribers.Add(new MessageSubscription<T>()
{
Message = message,
MessageActionWithArgs = action
});
}
public void Subscribe(string message, Action action)
{
subscribers.Add(new MessageSubscription<bool>()
{
Message = message,
MessageActionNoArgs = action
});
}
public void Send<T>(string message, T args)
{
IEnumerable<IMessageSubscription> matches = subscribers.Where(x => x.Message == message && x.PayLoadType == typeof(T));
foreach (IMessageSubscription sub in matches.ToList())
{
sub.InvokeMessageAction((T)args);
}
}
public void Send(string message)
{
IEnumerable<IMessageSubscription> matches = subscribers.Where(x => x.Message == message);
foreach (IMessageSubscription sub in matches.ToList())
{
sub.InvokeMessageAction();
}
}
}
So, for example, MainViewModel would listen for a message such as "ActiveViewModelChangeRequest", and other viewmodels would send that message when they need to become active. So, in MainViewModel you would have something like this:
public MainViewModel()
{
messageService.Register<ViewModelBase>("ActiveViewModelChangeRequest", UpdateActiveViewModel);
}
private void UpdateActiveViewModel(ViewModelBase viewModel)
{
this.CurrentVM = viewModel;
}
And then in UserListVM you would have:
private void OnUserSelect(object sender, UserSelectionEventArgs e)
{
UserVM viewModel = new UserVM(SelectedUser);
messageService.Send<ViewModelBase>("ActiveViewModelChangeRequest, viewModel);
}
There's a lot of reading material available on the messenger pattern for MVVM applications. I would suggest reading up on this.

Resolve region manager in wpf

I am trying to do this in a specflow step definition file, so that I can create an object of view model and make method calls to it.
But I get an error saying "Interface cannot be resolved: Microsoft.Practices.Prism.Regions.IRegionManager (resolution path: TestClass)". What is that I am doing wrong?
public class TestClass
{
private IRegionManager _RegionManager;
[ImportingConstructor]
public TestClass(IRegionManger regionManager)
{
this._RegionManager = regionManager;
// stuff here
}
}
Are you expecting your test class to be instantiated by SpecFlow or via Prism? As both have dependency injection functionality.
So I wouldn't expect your test definition file to have any importing constructors or similar MEF attributes. Instead I would expect your test class to written more like
[Binding]
public class TestClass
{
[Given("I setup Prism")]
public void GivenISetupPrism()
{
// Call into prism
}
}
See the documentation on http://specflow.org for more details.

How to use singleton over multiple assemblies in design time

I have 3 assemblies:
MyApp.Views (uses MyApp.Data and MyApp.Metadata)
MyApp.Data (uses MyApp.Metadata)
MyApp.Metadata
I have an interface, say IMetadata. Then, I also have an implementation in MyApp.Metadata which I register in a singleton class:
IoCContainer.Instance.Register<IMetadata, Metadata>();
Then, in design time, I use an assembly that needs to use the metadata (but it's the MyApp.Data that resolves the type):
IoCContainer.Instance.ResolveType<IMetadata>();
But this fails. The IoCContainer.Instance does not contain the same interfaces (actually, it's empty). The singleton implementation is really basic:
public class IoCContainer
{
static IoCContainer()
{
Instance = new IoCContainer();
}
public static IoCContainer Instance { get; private set; }
}
Somehow, it looks like separate assemblies are loaded in separate app domains (or something like that). Anyone knows a solution for this?
Could be a threading issue. Your singleton instance could be instantiated twice by different threads. Have a look at http://www.yoda.arachsys.com/csharp/singleton.html. It explains it in more detail and provides you with a thread safe solution.
Ok, problem seems to be solved. It might have 2 causes:
First, sometimes visual studio "updates" your references to shared libraries so one points to the bin\debug\mysharedassembly.dll, and the other one still points to ....\lib\mysharedassembly. This is some kind of stupid behavior of VS2010 where it tries to outthink the developer.
Second, I had this definition of the IoC Container:
public class IoCContainer
{
static IoCContainer()
{
Instance = new IoCContainer();
}
private IoCContainer()
{
}
public static IoCContainer Instance { get; private set; }
}
Which I changed to:
public class IoCContainer
{
private static readonly IoCContainer _instance = new IoCContainer;
private IoCContainer()
{
}
public static IoCContainer Instance { get { return _instance; } }
}
Anyway, problem solved :)

Is this an acceptable practice of managing views in a WPF application using Prism?

I am writing an WPF MVVM application using Prism. A couple days ago I asked about best practices for managing different views and didn't get a whole lot of feedback. Sense then I have come up with a system that seems to work, but I want to make sure I wont get bit down the road.
I followed the tutorials at http://development-guides.silverbaylabs.org/ to get my shell setup and am confident that my modules are being registered well.
However, nowhere in those tutorials was an example of a view being replaced with a different view within a given region. This in general, seems to be fairly hard to find a good example of. So, today I rolled my own solution to the problem.
Essentially the module has a controller that keeps track of the current view, then when the user wants to switch views, it calls the Regions.Remove command and then the add command to replace it with the current view. It seems like there must be a more elegant solution to just switch between different registered views, but I haven't found it.
All the different possible views for a module are registered with the Unity container when the module is initialized.
The controller and the view switching function follows:
namespace HazardModule
{
public class HazardController : IHazardController
{
private object CurrentView;
public IRegionManager RegionManager { get; set; }
private IUnityContainer _container;
public HazardController(IUnityContainer container)
{
_container = container;
}
/// <summary>
/// Switches the MainRegion view to a different view
/// </summary>
/// <typeparam name="T">The class of the view to switch to</typeparam>
public void SiwthToView<T>()
{
if (CurrentView != null)
{
RegionManager.Regions["MainRegion"].Remove(CurrentView);
}
CurrentView = _container.Resolve<T>();
RegionManager.Regions["MainRegion"].Add(CurrentView);
}
}
}
Any feedback or other better solutions would be appreciated.
I have pretty much the same approach, so does a co-worker who has a bit more Prism experience than myself.
Basically I have a ViewController class which is a property in my ViewModelBase class. This enables all my ViewModels to have access to it in one go. Then in my ViewController class I have a few display management methods. The correctness of this approach is probably debatable but I found it to work quite well in my case
public TView ShowViewInRegion<TView>(string regionName, string viewName, bool removeAllViewsFromRegion)
{
var region = regionManager.Regions[regionName];
var view = region.GetView(viewName) ?? container.Resolve<TView>();
if (removeAllViewsFromRegion)
{
RemoveViewsFromRegion(region);
}
region.Add(view, viewName);
region.Activate(view);
if (regionName == RegionNames.OverlayRegion)
{
eventAggregator.GetEvent<PopupWindowVisibility>().Publish(true);
}
return (TView)view;
}
public void RemoveViewsFromRegion(string regionName)
{
RemoveViewsFromRegion(regionManager.Regions[regionName]);
}
private void RemoveViewsFromRegion(IRegion region)
{
for (int i = 0; i < region.Views.Count() + i; i++)
{
var view = region.Views.ElementAt(0);
region.Remove(view);
}
if (region.Name == RegionNames.OverlayRegion)
{
eventAggregator.GetEvent<PopupWindowVisibility>().Publish(false);
}
}
private static void DeactivateViewsInRegion(IRegion region)
{
for (var i = 0; i < region.ActiveViews.Count(); i++)
{
var view = region.ActiveViews.ElementAt(i);
region.Deactivate(view);
}
}
Then whenever I need to switch out a view or whatever I can just call from my ViewModel
public void ExecuteCreateUserCommand()
{
ViewController.ShowViewInRegion<IUserCreateView>(RegionNames.ContentRegion, ViewNames.UserCreateView, true);
}

Resources