Does the Application class in Prism Library store data persistently? - xamarin.forms

I am currently using the Prism Library to build a Xamarin.Forms application. Prism provides developers with an interface 'IApplicationStore' that exposes properties. I implement the interface in my application. I was wondering does the Properties dictionary exposed in the interface store data persistently to a user's device or is this data only available whilst the application is open or in the background? The documentation on the Prism Library Github page doesn't really specify this.

Here is the source code of ApplicationStore on Prism repo on Github:
using System.Collections.Generic;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Prism.AppModel
{
public class ApplicationStore : IApplicationStore
{
public IDictionary<string, object> Properties
{
get { return Application.Current.Properties; }
}
public Task SavePropertiesAsync() =>
Application.Current.SavePropertiesAsync();
}
}
So it's just a wrapper around Xamarin.Forms application properties.
If you want to persist the properties, just call SavePropertiesAsync() and it should be fine:
https://learn.microsoft.com/en-US/dotnet/api/xamarin.forms.application.savepropertiesasync?view=xamarin-forms

Related

Blazor/Razor Class Library. Dependency Injection

I am confused on how to use a Razor Class Library that requires injected objects.
I created a new razor class library project.
There is no program.cs file and hence no WebAssemblyHostBuilder to add services to?
How do I inject dependencies into the components?
A library is simply that. It's not an application. You load the DI objects in the application project. You can write extension classes in your library as a wrapper to load all the necessary objects. builder.Services.AddServerSideBlazor() is just such an extension.
Here's an example extension method for the Weather Forecast.
public static class ServiceCollectionExtensions
{
public static void AddWeatherServices(this IServiceCollection services)
{
services.AddSingleton<WeatherForecastService>();
}
}
And use it in the application startup:
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddWeatherServices();
You inject the services into your components as normal. If you use a component in an application and the necessary services aren't loaded the page on which the component is being used will throw an error.

Xamarin Forms: Open downloaded file in default Android/iOS application

I am using Xamarin Forms. I would like to download jpg file (it is done) and then open that jpg in default application on Android/iOS (opening photo browser with this photo). Of course photo is single example, I would like to open any file in default application.
I found several solutions native-only but my application is designed to be cross-platform. I though that I can use Launcher from Xamarin.Essentials package but apparently I can't.
How to achieve this?
You can have a try with Xamarin.Essentials: Launcher:
var fn = "File.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(file)
});
I found several solutions native-only
Opening something in another app is quite close to the system for a mobile application and there are some things to consider, which dependend on the platform. Usually, mobile apps run in a sandbox with very limited access to the surrounding system. Particularly this means that, if you downloaded a file to the sandbox of your app, other apps (which native viewers are), aren't allowed to access the file.
On Android, you can copy the file to a shared space (see Application.Context.GetExternalFilesDir(null)) and then open it. This might be possible with Essentials, but I'm not quite sure, but since we're on the Android platform anyway now, you could create an intent now anyway.
On iOS you create controllers from within your app (for example the QLPreviewController to preview the file) that may access items in your sandbox. Depending on the type of controller (e.g. UIActivityViewController) they may open other apps.
How to use this platform-independently?
Since you are programming a platform independent app, you'll have to take care that the correct class is called to the platform dependent work. There are several options how you can achieve this
Use the DependencyService
Use a real dependency injection framework
Use an abstract base class with initialization in the platform dependent projects
DependencyService
To use the Xamarin.Forms DependencyService you need two things
An interface for the functionality you'd like to implement
One implementation per platform
Assuming you hvae a simple interface to share a file
public IShareFile
{
void ShareFile(string fileName);
}
you can implement an implementation of this interface on each platform and add the DependencyAttribute to the assembly. e.g. for iOS:
[assembly: Dependency(typeof(MyApp.iOS.DeviceOrientationService))]
namespace MyApp.iOS
{
public class ShareFile : IShareFile
{
public void Share(string fileName)
{
// implementation goes here
}
}
}
The general scaffold is the same for Android, albeit the implementation differs.
Using a real dependency injection framework
Basically it's pretty much the same. You can skip the DependencyAttribute, though. In order to make the implementation available you'll have to get hold of the DI container from your platform specific code, which might be tricky. This might be an overshoot for a single dependency, but if you're using a DI container anyway and there are X dependencies, it might be worth the effort.
Using an abstract base class
Add an abstract base class to your project
public abstract class ShareFile
{
public static ShareFile Instance { get; protected set; }
public abstract void Share(string fileName);
}
and in your implementation in the platform specific project, you add an Init() method
internal class ShareFileImpl : ShareFile
{
public static void Init()
{
ShareFile.Instance = new ShareFileImpl();
}
public void Share(string fileName)
{
// implementation goes here
}
}
This init method must be called from your platform specific code. Most likely during initialization. The implementation can then be accessed via its abstraction from your platform independent code (of course you'll see only the abstraction, public methods added to ShareFileImpl won't be visible from your platform independent code).
ShareFile.Instance.Share(fileName);
A combination of the abstract class approach and dependency injection is also conceivable. When registering your classes in the DI framework, you could register the platform instance like
container.RegisterInstance<ShareFile>(ShareFile.Instance);
This way you can make use of the DI container features (e.g. constructor injection), while keeping the hassles of using the DI container from your platform specific project away from you. The drawback is, that you'll still have to call ShareFileImpl.Init() from your platform specfic code.

System.Net.Http not found in net core 2.0 class library

I have the following structure of my net core solution.
API - web api
Interfaces - class library
Implementation - class library
Models - class library
In the API startup.cs, I have registered the service like so:
services.AddHttpClient();
I have a class as such in the Implementation Project
using System.Net.Http;
public IHttpClientFactory ihttpClientFactory;
public class FooImplementation: IFoo {
public void someFooMethod(){
// here call client to fetch data from api
// process this data
}
}
I wanted to inject a IHttpClientFactory into this, however it is complaining that it cannot be found. How can I resolve this error? and Also, Is this the correct approach to pass IHttpClientFactory into this class library based on the project structure?
You do have to check the documentation of IHttpClientFactory carefully, which says,
Namespace: System.Net.Http
Assembly: Microsoft.Extensions.Http.dll
That's the hint on which NuGet package to use, so you should add a package reference to Microsoft.Extensions.Http.

How to inject dependencies using Ninject In ASP.NET WebForm?

I have a fair idea of using the Repository Pattern and have been attempting to "upgrade" our current way of creating ASP .Net websites. So i do the following
Create a solution with a class project called DataAccessLayer and another class project called BusinessLogicLayer. Finally a 3rd project which is my ASP .Net website (a normal site).
I add a dbml file to the DAL and drag a table, then in my BLL i add an interface and a class which implements this interface:
My interface
namespace BLL.Interfaces
{
interface IUser
{
List<User> GetAllUsers();
}
}
In my class
namespace BLL.Services
{
public class UserService : BLL.Interfaces.IUser
{
public List<User> GetUsers()
{
throw new NotImplementedException();
}
}
}
I know the code is not fully completed, but there for illustrative purposes.
So i right click the BLL project > Manage NuGet Packages > Searched for Ninject and found a few. I was overwhelmed with the number of entries returned after after further research i am lost in how to add Ninject to a normal ASP .Net website? Specifically which addin i require? As there are many MVC and reading further i think im a little confused.
I was trying to add it to the BLL project as thats where i THINK it should go so i can register my services in there.
Could anyone guide me in what i need to so in order to use Ninject entries but im not using MVC?
Install Ninject.Web either from "Package Manager Console" or NuGet.
Version is 3.2.1 as of this writing.
OR
It will install the following 4 packages -
Sample Service Class
public interface IUserService
{
List<string> GetUsers();
}
public class UserService : IUserService
{
public List<string> GetUsers()
{
return new List<string> {"john", "eric"};
}
}
Then add binding to ~/App_Start/NinjectWebCommon.cs.
In code behind page, property inject using [Inject] attribute.
In Addition in answer by win I would advise people not to get confused by using Constructor based injection in ASP.NET Webforms as Web Forms doesn't support constructor based injection simply. In default configuration they only support Property based Injections as already demonstrated by Win.

Which PreApplicationStartMethod should I use?

I noticed that when I installed StructureMap from NuGet into my ASP.NET MVC3 project, Dave Ebbo's WebActivator package was also added as a dependency.
WebActivator provides a PreApplicationStartMethod attribute and, in the boilerplate code added at install time, it is used to initialise the IoC container and dependency resolver in it's own class, instead of doing this inside Global.asax's Application_Start method.
Given that ASP.NET 4 already has its own System.Web.PreApplicationStartMethodAttribute why was it necessary for WebActivator to supply its own version and for StructureMap to use that?
I am guessing I don't have to use WebActivator's variant?
Added code for Darin:
using System.Web;
using System.Web.Mvc;
using StructureMap;
[assembly: WebActivator.PreApplicationStartMethod(
typeof(MyMvcApp.App_Start.StructuremapMvc), "Start")]
// or
[assembly: PreApplicationStartMethod(
typeof(MyMvcApp.App_Start.StructuremapMvc), "Start")]
namespace MyMvcApp.App_Start {
public static class StructuremapMvc {
public static void Start() {
var container = (IContainer) IoC.Initialize();
DependencyResolver.SetResolver(new SmDependencyResolver(container));
}
}
}
NuGet packages for DI containers in ASP.NET MVC 3 usually prefer to use WebActivator to avoid messing with any existing code that you might have in Application_Start. Ninject uses exactly the same approach.
You can have multiple WebActivator.PreApplicationStartMethod attributes in your application and prior to .NET 4.5 a single System.Web.PreApplicationStartMethodAttribute.

Resources