I am trying to implement MVVM pattern for my Windows Phone application. I have my Views in one project and App.xaml in another project. I added property IsTrial to App.xaml but I can't reach it from View by this code:
if ((Application.Current as App).IsTrial)
Because I didn't reference first project with App class but I can't do that because that would cause a circular dependency. What can I do? How can I access App class? Thanks
Create an interface in your Views project:
public interface ISupportTrial
{
bool IsTrial { get; }
}
Implement the interface in App.xaml.cs:
public class App: Application, ISupportTrial
{
...
}
Change the code where you access the app:
var trialApp = Application.Current as ISupportTrial;
if (trialApp == null)
{
throw new NotSupportedException("Application.Current should implement ISupportTrial");
}
else if (trialApp.IsTrial)
{
...
}
else
{
...
}
NOTE: Although this will probably work, I don't think that it's a good practice to access Application.Current. You might want to read some articles about Inversion of Control and Dependency injection.
Related
I'm starting learning MVVM cross, In the android app, I have a splash screen class:
[Activity(MainLauncher = true,
Label = "#string/app_name",
Theme = "#style/Theme.Splash",
NoHistory = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : MvxSplashScreenActivity
{
public SplashScreen() : base(Resource.Layout.SplashScreen)
{
}
}
and this is the Setup class:
public class Setup : MvxAndroidSetup
{
protected Setup(Context applicationContext) : base(applicationContext)
{
}
protected override IMvxApplication CreateApp()
{
return null;
}
}
the problem is that the debugger doesn't hit the constructor of the Setup Class, instead I get "An unhandled exception" after the constructor of the splash screen
EDIT
I've already defined the App class in the PCL project:
public class App : MvxApplication
{
public override void Initialize()
{
base.Initialize();
}
also defined the AppStart:
public class AppStart : MvxNavigatingObject, IMvxAppStart
{
public async void Start(object hint = null)
{
//hardcoded login for this demo
//var userService = Mvx.Resolve<IUserDataService>();
//await userService.Login("gillcleeren", "123456");
ShowViewModel<MainViewModel>();
}
}
The main reason behind this project is to understand the sequence of code required and executed by MVVM Cross, so I provide the minimum code till it runs successfully without runtime errors.
Update
I have read your code again more thoroughly and I can see the issue now. You defined the constructor of the Setup class as protected, which makes it invisible for activation.
On MvvmCross for Android the magic happens inside MvxAndroidSetupSingleton class (see the source code here) which searches for the Setup type you defined. The FindSetupType method looks for your defined Setup class first and then inside the CreateSetup method Activator.CreateInstance is used to build the Setup instance. The CreateInstance method variant used however searches only for public constructors, which means it doesn't find your protected one. The result is that it cannot build the Setup class and crashes.
Original answer
The reason this happens is that you have no Core libary that would define the MvvmCross App class and would initialize other required setup. I suggest you to start with a simple tutorial or to look into the official sample projects to see what is necessary to make MvvmCross work in a Xamarin.Android app.
i'm using in a MVC project autofac.
I've another project with the core business(dll library).
In this core, i want use autofac for retrieve some interface.
Now, if i'm in the MVC application i can use
DependencyResolver.Current.GetService<IMyService>();
for retrieve the service.
But in the library how can I retrieve the service without pass it as property in some class declaration?
DependencyResolver is defined only in MVC project.
Is it a best practice?
I see following issues with your approach:
DepdencyResolver is defined in System.Web.Mvc, and your BL-project should not reference that assembly.
You are using the Service Locator Pattern, which is declared an Anti-Pattern.
Avoid the System.Web.Mvc-dependency in your BL-project
I found a specific Locator<T> is a practicable approach, which circumnavigates the "open to everything"- and static-issue of the Service Locator Pattern:
public interface ILocator<T> // defined in some *CORE* project
{
T Locate();
}
public class AutofacLocator<T> : ILocator<T> // defined and injected in your *FRONTEND* project
{
public AutofacLocator(ILifetimeScope lifetimeScope)
{
this.LifetimeScope = lifetimeScope;
}
public virtual T Locate()
{
var service = this.LifetimeScope.Resolve<T>();
return service;
}
}
This can simply be registered as an open generic:
builder.RegisterGeneric(typeof(AutofacLocator<>))
.As(typeof(ILocator<>))
.InstancePerDependency();
So, instead of depending on the static DependencyResolver.Current, you create your own resolver, and inject it in the BL-class' ctor:
public class SomeBusinessLogic
{
public SomeBusinessLogic(ILocator<SomeDependency> someDependencyLocator)
{
}
}
Use Ctor-Injection instead of the Service Locator Pattern
Another approach would be, to simply define the dependency on a T-instance as a ctor-parameter, and let Autofac build the instance of your BL-class:
public class SomeBusinessLogic // defined in your *BL* project
{
public SomeBusinessLogic(SomeDependency someDependency)
{
}
}
var someBusinessLogic = DependencyResolver.Current.GetService<SomeBusinessLogic>(); // in your *FRONTEND* project
I have 5 modules and I am using EventAggregator pattern to communicate between modules. And it seems to me that my code becomes ugly and it is bad design to use EventAggregator in my project.
There are three ways to communicate between modules:
Loosely coupled events
Shared services
Shared resources
I would like to know more about communication by Shared Services. What I've found is an article about StockTrader application from Prism ToolKit.
Is there some more lightweight and clearer example of using Shared Services in Prism where it is possible to see talking between modules using Shared Services? (downloadable code would be highly appreciated)
In which way is your code getting ugly? The EventAggregator is a shared service, if you like.
You put a service interface in a shared assembly, and then one module can, say, push data into the service while another module get's the data from the service.
Edit:
Shared assembly
public interface IMySharedService
{
void AddData( object newData );
object GetData();
event System.Action<object> DataArrived;
}
First communicating module
// this class has to be resolved from the unity container, perhaps via AutoWireViewModel
internal class SomeClass
{
public SomeClass( IMySharedService sharedService )
{
_sharedService = sharedService;
}
public void PerformImport( IEnumerable data )
{
foreach (var item in data)
_sharedService.AddData( item );
}
private readonly IMySharedService _sharedService;
}
Second communicating module
// this class has to be resolved from the same unity container as SomeClass (see above)
internal class SomeOtherClass
{
public SomeOtherClass( IMySharedService sharedService )
{
_sharedService = sharedService;
_sharedService.DataArrived += OnNewData;
}
public void ProcessData()
{
var item = _sharedService.GetData();
if (item == null)
return;
// Do something with the item...
}
private readonly IMySharedService _sharedService;
private void OnNewData( object item )
{
// Do something with the item...
}
}
Some other module's initialization
// this provides the instance of the shared service that will be injected in SomeClass and SomeOtherClass
_unityContainer.RegisterType<IMySharedService,MySharedServiceImplementation>( new ContainerControlledLifetimeManager() );
The Prism Library repo on GitHub has an up to date version of the Stock Trader sample application, which includes service examples and source code for you to look at, and download.
https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/StockTraderRI
Let's say I have 5 separate assemblies with the following (assume the class name is different in each):
[Export(typeof(IService))]
public class Service: IService
{
// ...
}
And I have a class that will be a composite of these in my main assembly
public class CompositeService : IService
{
public CompositeService(IEnumerable<IService> services)
{
// ...
}
}
What I would like to do is have the Unity container resolve the CompositeService for the IService and have the MefContrib extension for Unity go and find the 5 other exports and inject them into CompositeService's constructor.
The problem is that you can't have N instances for a nameless unityContainer.RegisterType<IService> nor can you for named instances if they all have the same name.
I think I'm missing something simple in the combination of the 2 technologies (Unity + MEF) via the third (MefContrib) but can't seem to pick up on what it is.
Is this possible or is there a workaround? Eventually, I'm going for full bi-directional dependency injection and dynamic component discovery.
I think what is likely the best approach is to flip this around. Instead of trying to register your components via Unity, you actually leave the discovery of these parts to MEF. MEFContrib includes an Unity integration mechanism that allows your MEF composed parts to be injected into Unity components. This was original detailed at Piotr WŁodek's blog, whereby he also gives you a sample. Essentialy, the way it works is you can use a series of extension methods on your UnityContainer to register your catalogs. Internally, it will create the appropriate extension and wire up your container.
Here is a quick and dirty example, we'll create some interfaces:
public interface IUnityComponent
{
IEnumerable<IMefComponent> MefComponents { get; }
}
public interface IMefComponent
{
string Name { get; }
}
And then some sample parts which we'll export (via MEF):
[Export(typeof(IMefComponent))]
public class MefComponent1 : IMefComponent
{
public string Name { get { return "MEF Component 1"; } }
}
[Export(typeof(IMefComponent))]
public class MefComponent2 : IMefComponent
{
public string Name { get { return "MEF Component 2"; } }
}
Now, we'll create another part (this will be created via Unity):
public class UnityComponent : IUnityComponent
{
public UnityComponent(IEnumerable<IMefComponent> mefComponents)
{
// mefComponents should be provided from your MEF container.
MefComponents = mefComponents;
}
public IEnumerable<IMefComponent> MefComponents { get; private set; }
}
To wire it all up, we simply need to use the RegisterCatalog extension method on your UnityContainer (import MefContrib.Integration.Unity after you've added a reference to MEFContrib):
var container = new UnityContainer();
// Register the catalog - this handles MEF integration.
container.RegisterCatalog(new DirectoryCatalog("."));
// Register our Unity components.
container.RegisterType<IUnityComponent, UnityComponent>(new ContainerControlledLifetimeManager());
Now you should be able to grab the instance and enumerate the MEF-provided parts:
// Grab an instance of our component.
var instance = container.Resolve<IUnityComponent>();
foreach (var mefComponent in instance.MefComponents)
{
Console.WriteLine(mefComponent.Name);
}
note: 100% untested.
Just tried the same solution from Matthew here and it is working ok, Unity is picking up the exports from MEF and injecting them into the constructor (which accepts an IEnumerable<>).
Don't know if it can help you, but including both MefContrib and MefContrib.Integration.Unity can help: for a while I only had the latter included and encountered similar errors.
As a side note, keep in mind that all the registrations in Unity (coming from MEF exports) will be "nameless" so if you try ResolveAll<> you will get an empty collection and if you try Resolve<> you will get an exception if there is more than 1 implementation registered.
Right now we have a dll file that contains all the database calls and i can't change it. However i need to call i from my Mvc 3 project. The process to call it is simple, i use the following:
ManageProvider.GetProxy<T>(ident);
T is an interface that i want to get the class back from (its like an IoC of its own) and ident is the user identification class. So by calling
var classReturned = ManageProvider.GetProxy<ICommunity>(new UserIden{ Email = "test#test.com" });
I would get a class back with all the community functions.
Now i want to implement Unity in my Mvc 3 project. The question is, can i somehow add these calls to the dll file through unity?
I want to resolve the call by using:
var classReturned = myContainer.Resolve<ICommunity>(new UserIden{ Email = "test#test.com" });
How can i register this in Unity (or is it even possible) ?
Update:
1) Is it better to call the methods with the email/user ident instead of defining a Dependency property? (ex below)
2) There is a bout 20 or so interfaces in the dll file right now. Should i add them all to the same reposatory? (ex below)
public class ProxyWrapper : IDllRepository
{
[Dependency]
public UserIdent UserIdent { get; set; }
public ICommunity GetCommunity()
{
return ManageProvider.GetProxy<ICommunity>(UserIdent);
}
public IDesktop GetDesktop()
{
return ManageProvider.GetProxy<IDesktop>(UserIdent);
}
}
public interface IDllRepository
{
ICommunity GetCommunity();
IDesktop GetDesktop();
}
Whats the best way and how would i call it from my code?
Does the [Dependency] attribute also fall into the Service Locator anti pattern?
Update 23.05.11
1) Yes, something like that. They contain all the logic that is provided to all the projects that includes the dll file.
Regarding the ManagerProvider. It accepts an interface and returns the class that is mapped to this interface. So for the community, the interface looks like this (removed a lot of calls to keep it short, there is also posts, comments, community create/update etc):
List<CommunityThread> GetThreads(int pStartRowIndex, int pMaximumRows, string pOrderBy, string pSearchExpression);
Guid? CreateThread(string pTitle, string pDescription, string pPostContent);
bool DeleteThread(Guid pThreadId);
List<CommunityThread> GetCommunityUserThreads(Guid pCommunityUserId);
2) What i can't update is how the ManageProvider.GetProxy works. The GetProxy is a class in the dll file that is hardcoded. Here is the part for the community. The class does the same for all the other interfaces as well, if typeof(interface) ... return class.
private static IManageProxy GetProxyForInterface<T>(UserIdent pIdent)
{
....
if (typeof(T).Equals(typeof(ICommunity)))
return new PCommunity();
....
}
3) Once registered using this new wrapper class, i can call it through the following code (MvcUnityContainer is a static class that only has a property called Container):
var c = MvcUnityContainer.Container.Resolve<IBackendRepository>(new PropertyOverride("UserIdent",
new UserIdent()));
Global.asax
IUnityContainer container = InitContainer();
MvcUnityContainer.Container = container;
DependencyResolver.SetResolver(new UnityMvcResolver(container));
The question is, do i need the static class MvcUnityContainer? Is it possible to configure the DependecyResolver to do that for me? Something like (problem is that it doesn't accept the override parameter):
var c = DependencyResolver.Current.GetService<IBackendRepository>(new PropertyOverride("UserIdent", new UserIdent()));
I think you need to hide the creation behind another abstraction, for instance:
public interface ICommunityRepository
{
ICommunity GetByEmailAddress(string address);
}
public class ManageProviderCommunityRepository
: ICommunityRepository
{
public ICommunity GetByEmailAddress(string address)
{
var id = new UserIden { Email = address };
return ManageProvider.GetProxy<ICommunity>(id);
}
}
This will hide both the ManageProvider and the UserIden behind this abstraction, and allows you to replace it later on with something more useful and makes testing easier.
Registration now is very easy:
RegisterType<ICommunityRepository, ManageProviderCommunityRepository>();
Instead of calling myContainer.Resolve (as you do in your example), inject the dependencies in your classes. This prevents you from using the Service Locator anti-pattern.
Perhaps you could do something like this, using the InjectionFactory:
myContainer.RegisterType<ICommunity>(
new InjectionFactory(c => ManageProvider.GetProxy<ICommunity>(new UserIden {Email = "test#test.com"})));
var classReturned = myContainer.Resolve<ICommunity>();
... Though you wouldn't be able to pass the UserIden as a parameter to the Resolve call, so I'm not sure if this is what you want.
To register all the public classes of the assembly you could perhaps iterate over Assembly.GetTypes() and register them in the same way?