Is it possible to referencing the specific Xamarin.IOS into Xamarin Form - xamarin.forms

We are trying to combine the Xamarin code that one is created using Xamarin Form (non XAML) and the other one is purely Xamarin.IOS.
We look at the library of Xamarin.Essential and it looks it doesn't have CoreMotion.CMPedometer (iOS) as we need to count the steps.
Is it possible to run the code within the Xamarin Form (shared) to handle specific OS?
Thanks

Yes, you need to use a Dependency Service.
All of the doco can be found here ... https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/dependency-service/introduction
An example is shown here in relation to device information (which has been cut down for simplicity reasons)
Firstly, you create an interface in your .NET standard/PCL project (if you're not using shared that is, which is likely the case).
using System;
namespace MyApplication.Interfaces
{
public interface IDeviceInfo
{
String GetDeviceModel();
String GetDeviceVersion();
}
}
Then down in your platform specific project, create a Dependency Service that implements that interface and directs the compiler to recognise the class as a Dependency Service.
using System;
using MyApplication.Interfaces;
using UIKit;
[assembly: Xamarin.Forms.Dependency(typeof(MyApplication.iOS.DeviceInfo))]
Namespace MyApplication.iOS
{
public class DeviceInfo : IDeviceInfo
{
UIDevice _device;
Public DeviceInfo()
{
_device = new UIDevice();
}
public string GetDeviceModel()
{
return _device.Model;
}
public string GetDeviceVersion()
{
return _device.SystemVersion;
}
}
}
Now from your .NET standard/PCL project, you can call the dependency service as required.
var deviceModel = DependencyService.Get<IDeviceInfo>().GetDeviceModel();
The above is specific for iOS which means you'd then need to implement the same concept for Android and UWP (or whatever is applicable).
See if that helps you.

Related

Move container registrations to a new assembly with Prism.Unity.Forms

I'm currently using Prism with Unity in a Xamarin.Forms project.
I'm using
protected override void RegisterTypes(IContainerRegistry containerRegistry) {}
to register my classes in App.xaml.cs, but as my project grows, so does this method / numbers of usings, etc.
I thought about offloading some of the registrations to their respective namespaces. That is, if I have a namespace for Users, I can have a class like this:
public sealed class UsersRegistry : IRegistry {
public UsersRegistry(IUnityContainer container)
{
container.RegisterType<IUserService, UserService>();
}
}
I started by using assembly scanning to find all classes that implement IRegistry, but I'm coming up a little short on how to create the class and pass in the container used by Prism.
I was attempting something like this:
var registries = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(type => typeof(IRegistry).IsAssignableFrom(type) && !type.IsInterface);
foreach (var type in registries) {
var instance = Activator.CreateInstance(type, <get unity container here>);
}
But I'm not certain this is the correct direction.
Also, it doesn't have to be this particular way. My main goal here is to break out the registrations for navigation and my various types into a more manageable system.
Any help would be appreciated.
Prism provides this functionality in the form of modules.

IContainerRegistryExtensions how to register an instance as singleton

I am trying to migrate an old Prism Xamarin Form project to latest Prism and XF version.
I'd like to register a factory for creating connections like this Func<SQLiteConnection>:
public class AndroidInitializer : IPlatformInitializer
{
string DbFilePath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "test.db3");
public void RegisterTypes(IContainerRegistry container)
{
container.RegisterSingleton<Func<SQLiteConnection>>(() => new SQLiteConnection(DbFilePath));
}
}
Howeve this doesn't work, there's no overload which takes an instance like I was used to do in old Prism Unity version.
The ContainerRegistry is intentionally basic to handle the 90+% of registrations that you need in a consistent manner regardless of which container you're using. You can continue to use the underlying container for more advanced registrations.
For both DryIoc and Unity it would be:
containerRegistry.GetContainer().SomeContainerSpecificMethod();
where SomeContainerSpecificMethod would match what you had in Prism 6.3
Another possibility is to use RegisterInstance to register a single instance of a class. Not sure if this has implications for object lifetime though.
var connection = new SQLiteConnection(DbFilePath)
container.RegisterInstance(connection);

MEF Error message - VS2010

Can anybody help me with explaining this error message please:
system.componentmodel.composition.changerejectedexception
The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error.
The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint:
ContractName Itok.BusinessLogic.Interfaces.IFolderService
RequiredTypeIdentity Itok.BusinessLogic.Interfaces.IFolderService
Resulting in: Cannot set import 'Itok.Web.Photos.Presenters.DefaultPresenter._folderService (ContractName="Itok.BusinessLogic.Interfaces.IFolderService")' on part 'Itok.Web.Photos.Presenters.DefaultPresenter'.
Element: Itok.Web.Photos.Presenters.DefaultPresenter._folderService (ContractName="Itok.BusinessLogic.Interfaces.IFolderService") --> Itok.Web.Photos.Presenters.DefaultPresenter
Here is the IFolderService.cs:
using System;
using System.Collections.Generic;
using Itok.Entities;
namespace Itok.BusinessLogic.Interfaces
{
public interface IFolderService
{
List<Folder> GetFriendsFolders(Int32 AccountID);
void DeleteFolder(Folder folder);
List<Folder> GetFoldersByAccountID(Int32 AccountID);
Folder GetFolderByID(Int64 FolderID);
Int64 SaveFolder(Folder folder);
}
}
And this is the exporting class definition, FolderService.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Itok.BusinessLogic.Interfaces;
using System.ComponentModel.Composition;
using Itok.DataAccess.Interfaces;
using Itok.Common;
using Itok.DataAccess;
using Itok.Interfaces;
using Itok.Entities;
namespace Itok.BusinessLogic
{
[Export(typeof(IFolderService))]
[Export(typeof(ICache))]
public class FolderService : IFolderService
{
[Import]
private IFriendRepository _friendRepository;
[Import]
private IFolderRepository _folderRepository;
[Import]
private ICache _cacheService;
public FolderService()
{
MEFManager.Compose(this);
}
public List<Folder> GetFriendsFolders(Int32 AccountID)
{
List<Friend> friends = _friendRepository.GetFriendsByAccountID(AccountID);
List<Folder> folders = _folderRepository.GetFriendsFolders(friends);
folders.OrderBy(f => f.CreateDate).Reverse();
return folders;
}
public void DeleteFolder(Folder folder)
{
if (_cacheService.Exists(folder.AccountID.ToString()))
{
_cacheService.Delete(folder.AccountID.ToString());
}
_folderRepository.DeleteFolder(folder);
}
public List<Folder> GetFoldersByAccountID(int AccountID)
{
List<Folder> cachedFolders = _cacheService.Get(AccountID.ToString()) as List<Folder>;
if (cachedFolders != null)
{
return cachedFolders;
}
else
{
cachedFolders = _folderRepository.GetFoldersByAccountID(AccountID);
_cacheService.Set(AccountID.ToString(), cachedFolders);
return cachedFolders;
}
}
public Folder GetFolderByID(Int64 FolderID)
{
return _folderRepository.GetFolderByID(FolderID);
}
public Int64 SaveFolder(Folder folder)
{
return _folderRepository.SaveFolder(folder);
}
}
}
I thank you prior to any help for saving my time.
The error message means that MEF is looking for a class that is exported with the interface IFolderService but there isn't one in the container.
To investigate this, firstly check that there is a class that exports that interface and if there is, then look into whether that class being picked up by the container or not and thirdly, if neither of those resolve the issue, look into whether the class that is exported with the interface IFolderService has some other imports that can't be satisfied.
Finally, I found the Solution for the problem. It has got has nothing to do directly with IFolderService that MEF was pointing to. The App has dependencies on a component (FolderService) in the business logic, which in turn is dependent upon an interface ICache, and an implementation wrapper, Cache.cs. ICache, specified by a contract name Itok.Interfaces.ICache, had been exported FOUR times (on just one Import). This was left unnoticed while I was trying to scale the solution. MEF couldn't tell which Export to use. The real problem is that MEF was pointing to a class two levels upper the chain!
Thanks TomDoesCode for looking at the problem, and I hope this will help others who'll get a similar problem.
A long term solution for this problem would be if you have many Exports that will satisfy an Import, you'll probably have two options:
I) Change the [Import] with [ImportMany]. Then during runtime, decide which import to use for the contract. Ask yourself if just picking up the first available, or using one at a time in random.
II) Use [ImportMany] in conjunction with Metadata in order to decide which Import to use.

Adding Wcf Service does not allow namespace access

I have created a wcf service called ServiceIRE. I add a service reference to my project by right clicking on th eproject in solution explorer and clicking add Service Reference. I am able to discover my created service and click ok after specifying the namespace ServiceReference1. All files seem to be generated properly.
I then go to the codebehind and try to add a using statment "using ServiceReference1;". This is unrecognized by the file even though the namespace apparently exists in the same project.
Any help would be greatly appreciated.
ServiceIRE.cs
namespace FakeIREServiceLibrary
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ServiceIRE : IServiceIRE
{
public string GetData()
{
Random rnd = new Random();
var randomNumber = rnd.Next(10);
Random rndID = new Random();
var randomNumberID = rnd.Next(10000);
Thread.Sleep(randomNumber*1000);
return string.Format("Thread # {0} returned in {1} nanoseconds", randomNumberID, rnd.Next());
}
}
IServiceIRE.cs
namespace FakeIREServiceLibrary
{
[ServiceContract]
public interface IServiceIRE
{
[OperationContract]
string GetData();
}
}
Page.aspx.cs
using ServiceReference1; //THIS IS NOT RECOGNIZED
Thank you in advance :)
What's the default namespace for your project?
I believe you have to do something like "using DefaultNamespaceForProject.ServiceReference1;"
You can find the default namespace by right clicking your project.. clicking Properties, and then going to the Application tab.
You can find the namespace of the service client generated by Visual Studio by looking at the Reference.cs file within the Service Reference after you show all files for that project. The default is [Project namespace].[Namespace specified].
It's possible that it did NOT generate the file because of an error. That may be the behavior you're seeing.
I would also encourage you to NOT use Add Service Reference, but to instead use a ChannelFactory or build a reusable service client.

Versioning of REST API Built With ASP.NET MVC 3 - Best Practices

I am wondering if there is a best practice for creating a REST API with ASP.NET MVC 3? At the moment I am thinking of creating a controller for each version of the REST API. For example, so far I have:
public class V1Controller : Controller
{
public V1Controller()
{
}
public ActionResult GetUser(string userId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
public ActionResult GetUsersByGroup(string groupId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
}
Then for the views I overwrite the _ViewStart.cshtml to remove the layout and then I have Results.cshtml that just outputs the data that is formatted in the controller action, right now JSON. Having every single REST call in one controller seems like a bit too much but it is the best way I can think of so that I can keep clean separate versions of the API so that when it comes to creating version 2 of the API, I can create a V2Controller and not break the existing API to give people time to switch over to the new API.
Is there a better way to create a REST API with ASP.NET MVC 3?
I was able to find a decent solution using MVC's use of Areas.
First, I wanted to have my API follow this URL Definition:
http://[website]/[major_version]_[minor_version]/{controller}/{action}/...
I also wanted to break up the different versions in separate Project files and use the same Controller names in each version:
"../v1_0/Orders/ViewOrders/.." => "../v2_3/Orders/ViewOrders/.."
I searched around and found a workable solution with the use of MVC Areas.
I created a new project in my solution called "Api.Controllers.v1_0" and, as a test, put a SystemController.cs file in there:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class SystemController : Controller
{
public ActionResult Index()
{
return new ContentResult() {Content = "VERSION 1.0"};
}
}
}
I then added a v1_0AreaRegistration.cs file:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class v1_0AreaRegistration : AreaRegistration
{
public override string AreaName
{
get{ return "v1_0";}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"v1_0",
"v1_0/{controller}/{action}/{id}",
new { controller = "System", action = "Index", id = UrlParameter.Optional }
);
}
}
}
I walked through the same steps above for a "..v1_1" project with the corresponding files in there, added the projects as references into my "Api.Web" MVC project and was off and running.
If all you are returning is JSON, you do not need a view. Jusr return
new JsonResult(){Data = Data};
Look in here.
Also in terms of versioning, versions can be implemented as different controllers or as extra methods in the same controller. But without knowing why you would need versions and why your clients (which I assume are browsers) would need to know about versioning is not clear from your question.
A controller such as the one you posted in your example code should always keep that methods that you have now for instance GetUsersByGroup() with the same signature. I don't see how there could be a different version of that method.
The inputs are group and repository (which I believe comes from DI). The output is a list of users in JSON format. That's all that matters to the users of the API. What you do inside this method is no one's business.
You should think more of inputs and outputs. You shouldn't be changing the signatures of existing actions unless it is really neccessary to do so.
Think of the controller class in terms of implementing the interface. You have an interface and controller class is it's implementation (I mean you don't need to have it but just think of it in that way). You will rarely change the interface once one or several classes implement it. But you might add the methods to it. And that requires only changes in implementing classes - it does not break the functionality of the API and everyone who's using it will be able to continue using it.

Resources