Resolve region manager in wpf - 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.

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.

Unit test MVVM commands

I have a new WPF MVVM project and would like to write "some useful" unit tests for my ViewModel.
My ViewModel class:
public class ConsignorViewModel : ViewModel
{
...
#region Commands
void NewModel()
{
_model = new Consignor();
RaisePropertyChanged(String.Empty, validatePropertyName: false);
}
void SaveModel()
{
... //some logic to save
}
public override ICommand New { get { return new RelayCommand(NewModel); } }
public override ICommand Save { get { return new RelayCommand(SaveModel); } }
#endregion
}
I would like to unit test those commands. What is the best way to do so?
At the moment my unit test method just looks like this:
[TestMethod]
public void TestCommands()
{
//Arrange
//Act
//Assert
////New Command
Assert.IsNotNull(_consignorViewModel.New);
Assert.IsTrue(_consignorViewModel.New is RelayCommand);
////Save Command
Assert.IsNotNull(_consignorViewModel.Save);
Assert.IsTrue(_consignorViewModel.Save is RelayCommand);
}
I would like to test the behaviour/result of an command.
When testing the "new" command I would like to ensure that the model is "reset" (constructor call). At the moment this is not possible as my methods "NewModel" and "SaveModel" are not visible in the unit test which is correct as they're not part of the public interface. So I don't want to make them public ...
At the moment this is not possible as my methods "NewModel" and "SaveModel" are not visible in the unit test which is correct as they're not part of the public interface.
And they shouldn't be. You already know the solution to this problem, you even said it yourself:
I would like to test the behaviour/result of an command.
That's the point. With unit tests we verify observable effects. How does the user recognise that model has been reset? User has no knowledge of New method, nor should unit test. If New method has no obeservable side effect, visible from public POV, then you might just as well remove it from your code base.
Identify those publicly visible changes and test against them.

Ninject ActivationException in WinForms application

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.

Silverlight Prism MEF: why use ServiceLocator to get View instance?

In Prism's IModule Initialize() method, the RegisterViewWithRegion() method is called to map views and regions.
What is the difference between those two lines of code? Why use a ServiceLocator?
_regionManager.RegisterViewWithRegion("Region1", () => _serviceLocator.GetInstance<View1>());
_regionManager.RegisterViewWithRegion("Region1", typeof(View1));
Here is the whole ModuleInit.cs class for context:
namespace MyModule
{
[ModuleExport("MyModule.ModuleInit", typeof(MyModule.ModuleInit))]
public class ModuleInit : IModule
{
private readonly IRegionManager _regionManager;
public IServiceLocator _serviceLocator;
[ImportingConstructor]
public ModuleInit(IRegionManager regionManager, IServiceLocator serviceLocator)
{
_regionManager = regionManager;
_serviceLocator = serviceLocator;
}
#region IModule Members
public void Initialize()
{
_regionManager.RegisterViewWithRegion("Region1", () => _serviceLocator.GetInstance<View1>());
}
#endregion
}
}
[Edit]
The RegisterViewWithRegion Method MSDN site describes what the two different versions do:
RegisterViewWithRegion(IRegionManager, String, Func<Object>)
Associate a view with a region, using a delegate to resolve a
concreate instance of the view. When the region get's displayed, this
delelgate will be called and the result will be added to the views
collection of the region.
RegisterViewWithRegion(IRegionManager, String, Type)
Associate a view with a region, by registering a type. When the region
get's displayed this type will be resolved using the ServiceLocator
into a concrete instance. The instance will be added to the Views
collection of the region
So it seems to me that the only difference would be to use a ServiceLocator to resolve the type into an instance either immediately, or later when the region gets displayed?
[Edit2]
Found the answer elsewhere on Stackoverflow
That's because the main App is not supposed to know about modules.
When a module is loaded, it registers with the ServiceLocator and it has access to the RegionManager.
It can then, without the main app knowing anything about the newly loaded module, inject a view from the module into the main app (a new tab for example).
The ServiceLocator will ask MEF for dependencies, so you can always call _serviceLocator.GetInstance<View1>() parameterless, and MEF will go resolve whatever needs to be imported, no matter what you change in View1's constructor signature.

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 :)

Resources