Platform-specific IoC in MVVMCross - inversion-of-control

I'm giving a MVVMCross a spin, to see if it will be of use in some bigger projects coming up, and it's great. I like the navigation, viewModel location and general cross-platform approach, which is just what I need. However, I'm a bit stuck on splitting out some of the dependency injection depending on the platform.
So, we have the basic application, with a shared portable library, that initialises the service references when starting up:
public TwitterSearchApp()
{
InitaliseServices();
}
private void InitaliseServices()
{
this.RegisterServiceInstance<ITwitterSearchProvider>(new TwitterSearchProvider());
}
Fine. That defines the service implementations that will be used across all the platforms. But what about the situation where I will need different implementations on different platforms - for instance perhaps storage/caching, where the core requirement is the same, but needs to be handled differently on a phone than on a tablet.
I thought it might go in Setup somewhere:
public class Setup : MvxBaseWinRTSetup
{
public Setup(Frame rootFrame): base(rootFrame)
{
}
protected override MvxApplication CreateApp()
{
var app = new TwitterSearchApp();//set platorm specific IoC here maybe?
return app;
}
protected override void AddPluginsLoaders(Cirrious.MvvmCross.Platform.MvxLoaderPluginRegistry loaders)
{ // or perhaps here?
loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Visibility.WinRT.Plugin>();
base.AddPluginsLoaders(loaders);
}
}
but I'm not sure. I've seen the references to replacing the ViewModel locator, but is there are similar way of replacing the other IoC services?
thanks, great job on the framework in general, I really like how it works (apart from this bit, which I don't understand properly yet)
Toby

There are three basic options:
1. Add the platform specific services in your UI project and then register them in an override during setup - which override you use depends on when your services are needed, but for most cases you can just use the InitializeLastChance override which gets called at the end of initialization:
protected override void InitializeLastChance()
{
this.RegisterServiceInstance<IMyService>(new SingletonMyService());
this.RegisterServiceType<IMyService2, PerCallService2>();
base.InitialiseLastChance();
}
If 'last chance' is too late for your service - if you need the service during the core app startup - then you can override any initialisation step after InitializeIoC - e.g. InitializeFirstChance. For the list and order of initialisation steps, see InitializePrimary and InitializeSecondary in MvxBaseSetup.cs
2. Add the platform specific registration in some other bit of the UI code - e.g. in the constructor for a specific View (this option isn't used much... but you could use it in some odd cases, if you wanted to...)
3. Use a plugin - all plugins are is a wrapper around IoC. Plugins have the disadvantage that they add some development overhead (you have to add the separate projects and the plugin boilerplate files), but they have the advantages that they can be reused across apps and it's easier to write test apps and test harnesses for them. For more info on plugins, see Making mono cross platform support for Task/Intent and see http://slodge.blogspot.co.uk/2012/10/build-new-plugin-for-mvvmcrosss.html
My general advice - start with the first option and migrate out to a plugin if you want to reuse the code in later projects...

Related

Cocoapod library and multiples configurations embedding

After googling a lot regarding my need, I finally ask to this awesome community a way to achieve my goal.
I need to create a swift library with cocoapod, and integrate multiple build configurations. I want to create 3 schemes on my project to switch easily environments variables (like target API, log level, and many more).
I really want to do this on library side, not on app-side, since it's for debug & testing purposes, and finally, applications which embed this pod will only use the "Release" build (except us, developers who maintain this library)
I tried opening the _Pods.xcodeproj and doing update in this file (create *.xcconfig files I need, mapped to configurations schemes) but disappear after ran a "pod install".
Not sure at all if you can do that hack on library side. Looks weird.
But the best practice would be:
When initializing and configuring libraries, endpoints etc (all you need to change between schemes), just check which one is used, and pass different parameters
create a file, FE Constants
struct Constants {
static var libraryApiKey: String {
#if DEBUG
return "debugKey"
#else
return "productionKey"
}
And when initializing
Library.initialize(withKey: Constants.libraryApiKey)

How to write a custom module for spring data

I need to extend spring data in order to support my own custom backend. From the spring data website, it seems that it is possible to add community modules to the framework, which in turn enables you to support a custom backend. However, I can't seem to find some code examples/docs illustrating the module implementation mechanism.
Even a basic example using a file-based persistence would be very helpful.
You just have to extend it then you can override the methods and add your own. If you're using IntelliJ, just implement/extend (for example) CrudRepository, execute Generate Code and select Implement methods or Override methods.
public MyRepository extends CrudRepository<T, Long>{
//in Mac, you press command + N. Then select Override methods.
//in Windows, I don't think Generate Method is given a shortcut. You can find it in the menu bar
}

How do Service / SourceProviders work in Eclipse 4 RCP 2.0?

I've been busily getting with the future and migrating an old eclipse 3.7 application over to Eclipse 4 and whilst I'm happy with the application model for porting all the views I have a number of source providers that I am unsure about porting wise. I've been using a few tutorials on Eclipse 4 including this Tutorial from good old Lars but none seem to cover this particular element.
For a small amount of Context my existing application has a few classes extending AbstractSourceProvider that are registered in the org.eclipse.ui.services extension point. My views register themselves as listeners to these services using the ISourceProviderService.getSourceProvider(key) function from the workbench and update themselves if that source fires a sourced changed event. I also have a few providers that reference each other some times too so I'm wondering if this will still work with injection.
What sort of model is used in Eclipse 4?, should I just use the same old extension point? Can these extension point services be injected in to the views in the new cool anotationy way?
What gives?
You can create a service in a number of ways:
Create an instance of your service class and put it in the IEclipseContext. This is often done in an 'Addon':
public class MyAddon
{
#PostConstruct
void postConstruct(IEclipseContext context)
{
MyService myService = ContextInjectionFactory.make(MyService.class, context);
context.put(MyService.class, myService);
}
}
The 'Addon' is declared in the application.e4xmi file.
You could also create the service like this in the LifeCycle class for the RCP.
An OSGi service will automatically be added to the Eclipse context.
You can use a Context Function which uses an OSGi service but doesn't create the actual service until it is needed.
In all cases you reference the service by injection:
#Inject
MyService myService;
Note that injection is only done on objects created by Eclipse from objects described in the application.e4xmi. It is possible to do injection on other objects using ContextInjectionFactory.

Implementing multiple views via GWT-platform?

I'm implementing a web application which will support different views according to different browsers. For example, In mobile browsers, it will show a smaller view to users with less UI elements. But we'd like to use same presenters.
I have a solution on hand - adding browser type detecting logic in ClientModule, e.g:
if (browser == "iphone") {
bindPresenter(HomePresenter.class, HomePresenter.MyView.class, HomeView.class, HomePresenter.MyProxy.class);
} else if (browser == "ipad") {
bindPresenter(HomePresenter.class, HomePresenter.MyView.class, IPadHomeView.class, HomePresenter.MyProxy.class);
} else {
bindPresenter(HomePresenter.class, HomePresenter.MyView.class, IPhoneHomeView.class, HomePresenter.MyProxy.class);
}
I'm wondering if it is possible to use some ways like deferred binding in GWT-platform. (but I'd like to follow GWT-plarform's structure rather than adding deferred binding code in xxx.gwt.xml).
So my questions are:
1) Are there any other ways to implement the feature mentioned above?
2) Which way is the best, and why?
Thanks in advance!
Best regards,
Jiakuan W
There is an example in the gwt samples folder that does something like you are wanting. I use a version of the sample code in my project -except using Gin to handle the clientfactory functionality. The sample is called mobilewebapp. It involves using a formfactor method in your .gwt.xml to determine which system you are on - in this case it breaks it down into desktop, mobile, and tablet. Then later in your gwt.xml it trades out client factories based on the form factor - I trade out gin models instead. Here is a link to the source for mobilwebapp
GWT does not allow you to set custom user agent types. You're limited to their set of gecko, gecko1_7, safari, IE6, IE7, IE8, and opera.
That being said, you can access the user agent directly and set your logic to switch accordingly with Window.Navigator.getUserAgent(), or via a property provider.
See this similar question on how to do mobile browser detection in GWT for MVP.
Check the gwtp google group, its a good source, and someone posted a pdf about his efforts regarding the sake problem in there.
Anyway, if I recall correctly, he holds multiple gin modules for each client with the presenters and views, runs custom js code on loading and than installs the correct module on the the ginClinet class.

Manage autofac container setup

One of my team members decided to use autofac on one of our services and because we wanted to try it out we stuck with it.
Now some time has passed and the container setup method has grown! It so big that we are having problems with it.
Splitting it up did not bring the results we looked for. Maybe we are just using it wrong.
So my question is: How can we manage the container setup? Can we dump into XML or are there any other best practices?
There are many ways to manage container setup with autofac.
One of the most common ways is to use a Module and register it with the builder. You can break up multiple groups of registration this way:
public class DALModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<SomeDataSomething>().As<IDataSomething>();
builder.Register<SomeOtherSomething( c => SomeOtherSomething.Create());
//and so on
}
}
Then register these broken up modules with the builder either via code or XML.
(a simple call to builder.RegisterModule( new DALModule()) would do it here). See the wiki page on Structuring with Modules.
Or, you can use only XML files (or use XML and modules together). See the wiki page on XML config for this.