MVVM Light for Xamarin Forms and WPF - wpf

I'm trying to make an cross-plattform app, that will work for Xamarin.Forms and WPF (like this: https://github.com/C0D3Name/XamFormsWpf) in combination with MVVM light.
MVVM Light is quite new to me and i didn't find a clear tutorial for what i want to do. On Xamarin.Forms the DependencyInjection is done by
SQLiteConnection database = DependencyService.Get<ISQLite>().GetConnection("db.sqlite");
How is this done in MVVM light? Do i have to pass the different plattform-implementations of ISQLite in as parameter?
I already created the ViewModelLocator in my PCL:
public class ViewModelLocator
{
/// <summary>
/// Register all the used ViewModels, Services et. al. witht the IoC Container
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
// My DataService is using the connection from ISQlite
SimpleIoc.Default.Register<IDataService, DataService>();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
}
public interface ISQLite
{
SQLiteConnection GetConnection(string sqliteFilename);
}
As far as i understood the SimpleIoc, i have to register the interface to a concrete implementation, but how does my DataService know about the correct ISQLite Implementation?
I hope my question is understandable.

From official docs:
SimpleIoc - A very simple IOC container with basic functionality needed to register and resolve instances.
DependencyService - Xamarin.Forms allows developers to define behavior in platform-specific projects. DependencyService then finds the right platform implementation, allowing shared code to access the native functionality.
So you would want to use SimpleIoc to create your PCL dependency injection graph (IDataService for example)
And you will have to use DependencyService to provide platform specific functionality. One example for DependencyService use would be loading a html file located on the device into webview. Since the locations of assets on iOS and Android are different you will have add platform specific implementation for base url and then use DependencyService in your pcl. Another example would be IO.
So in your case if you need platform specific implementations of ISQlite you will have to use DependencyService. If not you may want (or not) to use SimpleIoc to add concrete implementation of ISQlite interface to your dependency graph.
Hope that helps.
Also have a look at Akavache. We use it with a great success in Xamarin.Forms projects.

Finally i found a working solution. The (async) Sqlite-Connection is used as parameter for my ViewModelLocator
public class App : Application
{
private static ViewModelLocator locator;
public static ViewModelLocator Locator
{
get
{
if (locator == null)
{
var connection = DependencyService.Get<ISQLite>().GetConnection("db.sqlite");
locator = new ViewModelLocator(connection);
}
return locator;
}
}
}
...and the locator injects the connection into the DataService constructor:
public class ViewModelLocator
{
public ViewModelLocator(SQLiteConnectionWithLock connection)
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<IDataService>(() => new DataService(connection));
// ViewModels
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main => ServiceLocator.Current.GetInstance<MainViewModel>();
}

Related

Modules registration in Prism 7.1

In Prism 7.1, the IModule interface has changed from version 6.3, and now exposes the two methods RegisterTypes (IContainerRegistry containerRegistry) and OnInitialized (IContainerProvider containerProvider). I ask forgiveness, but I cannot understand how I have to register the Views implemented in the Module. it's probably so simple that I can not see the solution to the problem. Can you give me an example to finally make me understand how I should do? Wherever I looked, I found only examples regarding version 6.3, which I know rather well ..
Prism 7.X introduces an abstraction around the DI Container. There were a number of reasons for this but the top two are:
Many of the support questions from the community to the Prism team revolved around how to do something with a container that has nothing to do with the Prism team.
By abstracting the container it makes scenarios around sharing code and swapping out containers easier.
It's also important to understand that by abstracting the Container we've also made changes to the Container Extensions responsible for registering Views. Specifically we now have them on the IContainerRegistry. So given the sample Prism 6.X Module here:
public class ModuleA
{
private IUnityContainer _container { get; }
public ModuleA(IUnityContainer container)
{
_container = container;
}
public void Initialize()
{
// register stuff
_container.RegisterViewForNavigation<ViewA>();
// Setup Event listeners etc...
var ea = _container.Resolve<IEventAggregator>();
}
}
We would update this to:
public class ModuleA
{
public void OnInitialized(IContainerProvider containerProvider)
{
// Setup Event listeners etc...
var ea = containerProvider.Resolve<IEventAggregator>();
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
// register stuff
containerRegistry.RegisterForNavigation<ViewA>();
}
}
it's probably so simple that I can not see the solution to the problem
Just use RegisterTypes - registering a view is registering a type, after all.

Optional Dependency at Composition Root

I've written a WPF app that has two different main windows. I don't know which one to launch until runtime by looking up what kind of user is using the program in a database. The code I currently have works but Castle Windsor is doing tons of extra work by newing up the object graphs for both kinds of windows.
private readonly IMainWindow _mainWindow;
private readonly ISimplifiedMainWindow _simplifiedMainWindow;
public MainClass(
IMainWindow mainWindow,
ISimplifiedMainWindow simplifiedMainWindow)
{
_mainWindow = mainWindow;
_simplifiedMainWindow = simplifiedMainWindow;
}
public RunApp()
{ // pseudocode
if (user is fullUser) _mainWindow.Show();
else _simplifiedMainWindow.Show();
}
How do I defer creation of my window objects without resorting to making an abstract factory that will basically duplicate what Castle Windsor does anyway?
A factory is in fact the solution I'd recommend (and a solution I've successfully used multiple times in the past to solve this very problem).
I wouldn't implement the factory myself though, let Windsor do it (via a Typed Factory).
public interface IWindowFactory
{
IMainWindow FullUserWindow();
ISimplifiedMainWindow SimplifiedUserWindow();
//optionally
void DestroyWindow(IWindow window);
}
Now you just need to tell Windsor to build a factory for that interface
container.AddFacility<TypedFactoryFacility>();
// later on, in your installer
container.Register(Component.For<IWindowFactory>()
.AsFactory()
.LifestyleTransient());
and your app code changes to:
public RunApp()
{ // pseudocode
if (user is fullUser) Show(factory.FullUserWindow());
else Show(factory.SimplifiedUserWindow());
}

Notify property changed in WCF service

I have a WPF application which calls WCF service methods through a Client which exposes these methods. Is there any way to bind my application to a property of the service, and to get notified when this property changes? I know INotifyPropertyChanged but I have some doubts about its efficiency in this case... Thanks
EDIT : Actually, all I want is my application to be notified of the changes that happen on the server side.
There are a couple of questsions here. You can bind your code to the client end of a WCF service and by using a partial class definition you can add an INotifyPropertyChanged interface to it so that it meets your design. But actually wiring up the mechanism for pushing updates from the server would be much harder.
In fact, Events will work over WCF, and reasonably performant i.e. you won't have the delay associated with polling. However I wouldn't try to squeeze your WCF code into fitting the INotifyPropertyChanged pattern. Instead use a more bespoke interface for the client/server comms and then expose the INotifyPropertyChanged back in the ViewModel.
Just add a delegate to your service, then call the service from your view model or code behind and reflect the changes with your properties that implement the INotifyPropertyChanged interface:
In Service:
public delegate void ServcieUpdate(SomeDataType data);
public ServcieUpdate OnServcieUpdated { get; set; }
When data is updated:
if (OnServcieUpdated != null) OnServcieUpdated(data);
In view model:
private ServiceClient serviceClient = new ServiceClient();
private ObservableCollection<SomeDataType> data = new
ObservableCollection<SomeDataType>();
public YourViewModel()
{
serviceClient.OnServiceUpdated += OnServcieUpdated;
}
public ObservableCollection<SomeDataType> Data
{
get { return data; }
set { data = value; NotifyPropertyChanged("Data");
}
public void OnServcieUpdated(SomeDataType data)
{
Data = data;
}
Please take a look at the Delegates (C# Programming Guide) page on MSDN in you are unfamiliar with using delegate objects.

Using Castle.Windsor with Windows Forms Applications

Up until this point, I have been learning IoC/DI with Castle.Windsor using ASP.NET MVC, but I have a side project that is being done in Windows Forms, and I was wondering if there is an effective way to use it for that.
My problem is in the creation of forms, services, etc. In ASP.NET MVC, there is a sort of 'Activator' that does this under the hood, but this isn't the case in Windows Forms. I have to create a new Form like var form = new fclsMain();, so a Form like ..
class fclsMain : System.Windows.Forms.Form
{
private readonly ISomeRepository<SomeClass> someRepository;
fclsMain(ISomeRepository<SomeClass> someRepository)
{
this.someRepository = someRepository;
}
}
Falls kind of short. I would basically have to do ...
var form = new fclsMain(IoC.Resolve<ISomeRepository<SomeClass>);
Which as I have had pointed out in at least three of my questions isn't smart, because it's supposedly not the 'correct' usage of IoC.
So how do I work with Castle.Windsor and Windows Forms? Is there some way to design a Form Activator or something? I'm really lost, if I can't make a static IoC container that I can resolve from, what can I do?
Here you are doing something that are not very "Dependency Injection"...
var form = new fclsMain(IoC.Resolve<ISomeRepository<SomeClass>);
The "new" is the problem...
You have to call
var form = IoC.Resolve<fcls>();
the form of type fcls must be correctly configured via Fluent Registration API o
In order to use the same Castle container throughout your entire application, create a static class like:
public static class CastleContainer {
private static IWindsorContainer container;
public static IWindsorContainer Instance {
get {
if (container == null) {
container = new WindsorContainer();
}
return container;
}
// exposing a setter alleviates some common component testing problems
set { container = value; }
}
// shortcut to make your life easier :)
public static T Resolve<T>() {
return Instance.Resolve<T>();
}
public static void Dispose() {
if (container != null)
container.Dispose();
container = null;
}
}
Then register/install all your components in the Main() method. You can also hook into the application shutdown event to call Dispose() (although this isn't critical).
Castle actually uses a Windows Forms app in their quick-start guide.
Edit:
The pattern I showed above is a variant of the service locator, which some people refer to as an anti-pattern. It has a bad reputation because, among other reasons, it liters your code base with references to Windsor. Ideally, you should only have a single call to container.Resolve<...>() to create your root form. All other services & forms are injected via constructors.
Realistically, you'll probably need a few more calls to Resolve, especially if you don't want to load every single corner of the application at startup. In the web world, the best practice is to hand off the container to the web framework. In the Windows Forms world you'll need to implement your own service locator, like above. (Yes, handing the container to the ASP.NET MVC framework is still a service locator pattern).
I've edited the above code example so that the static container is injectable; no resources are tied up in a static context. If you do end up creating your own service locator, you might also want to create a test utility like this one to make testing easier.
public static class TestUtilities
{
public static IContainer CreateContainer(Action<IContainer> extraConfig = null)
{
var container = new WindsorContainer();
// 1. Setup common mocks to override prod configuration
// 2. Setup specific mocks, when provided
if (extraConfig != null)
extraConfig(container);
// 3. Configure container with production installers
CastleContainer.Instance = container;
return container;
}
}
This makes a shortcut for creating a new container that looks a lot like the production version, but with some services replaced with mocks. Some example tests might look like:
[Test]
public void SubComponentWorksGreat()
{
using (var container = TestUtilities.CreateContainer())
{
var subComponent = container.Resolve<SubComponent>();
// test it...
}
}
[Test]
public void SubComponentWorksGreatWithMocks()
{
var repoMock = new Mock<IRepository>();
using (var container = TestUtilities.CreateContainer(c =>
c.Register(Component.For<IRepository>().Instance(repoMock.Object))))
{
var subComponent = container.Resolve<SubComponent>();
// test it with all IRepository instances mocked...
}
}
One last note. Creating a full container for every test can get expensive. Another option is to create the full container but only using nested containers for the actual tests.
You don't "have to" new-up a form, as you've said.
I use WinForms and never call "new FormName()". It's always a dependency itself. Otherwise I'd have to stuff the constructor full of service locator calls.
I might use a ServiceLocator (as in another answer) BUT only at the very top level.
For example I have a Command pattern implemented to intercept toolbar buttons.
Looks something like this:
public void Handle(string commandName)
{
var command = IoC.Resolve<ICommand>(RegisteredCommands[commandName]);
command.Execute();
}
Then, in a simplified case, this is the kind of code written everywhere else:
public class ShowOptionsCommand : Command, ICommand
{
private readonly IOptionsView _optionsView;
public ShowOptionsCommand(IOptionsView optionsView)
{
_optionsView = optionsView;
}
public void Execute()
{
_optionsView.Show();
}
}
Yes, I use a "service locator" but you will hardly ever see it.
That's important to me, because having service locator calls all throughout the code (eg in every class) defeats some of the point of using dependency inversion of control & needs extra work to be testable etc

Issue intercepting property in Silverlight application

I am using Ninject as DI container in a Silverlight application. Now I am extending the application to support interception and started integrating DynamicProxy2 extension for Ninject. I am trying to intercept call to properties on a ViewModel and ending up getting following exception:
“Attempt to access the method failed: System.Reflection.Emit.DynamicMethod..ctor(System.String, System.Type, System.Type[], System.Reflection.Module, Boolean)”
This exception is thrown when invocation.Proceed() method is called. I tried two implementations of the interceptor and they both fail
public class NotifyPropertyChangedInterceptor: SimpleInterceptor
{
protected override void AfterInvoke(IInvocation invocation)
{
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
public class NotifyPropertyChangedInterceptor: IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
I want to call OnPropertyChanged method on the ViewModel when property value is set.
I am using Attribute based interception.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class NotifyPropertyChangedAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
if(request.Method.Name.StartsWith("set_"))
return request.Context.Kernel.Get<NotifyPropertyChangedInterceptor>();
return null;
}
}
I tested the implementation with a Console Application and it works alright.
I also noted in Console Application as long as I had Ninject.Extensions.Interception.DynamicProxy2.dll in same folder as Ninject.dll I did not have to explicitly load DynamicProxy2Module into the Kernel, where as I had to explicitly load it for Silverlight application as follows:
IKernel kernel = new StandardKernel(new DIModules(), new DynamicProxy2Module());
Could someone please help? Thanks
Reflection can be really tricky in silverlight because of security issues.
Check Gabe's answer for this question, it's the same problem.
The good news is that you can achieve the same functionality you want using dynamic instead of proxies. Just extend your ViewModel from DynamicObject and override the TrySetMember method.
I hope it helps :)

Resources