Implement dependency injection in background services in Xamarin Forms using Prism

会有一股神秘感。 提交于 2019-12-24 02:45:23

问题


I am making use of Prism in my xamarin forms project.I was able to use dependency injection(constructor injection) in my View Model without any problems.I am also making use of background services to push long running tasks in the background.How do I inject dependency in my Background services?When I try to pass the interface object as a paramater to the constructor(SyncingBackgroundingCode) ,the object(SqliteService) is null.I have registered and resolved the objects in the dependency injection container. How to handle this case?Can anybody provide an example or link to implement this scenario?

This is the piece of code where im trying to implement dependency injection.

This is in Droid :-

    public class AndroidSyncBackgroundService : Service
         {
        CancellationTokenSource _cts;
        public override IBinder OnBind (Intent intent)
        {
        return null;
        }
        public override StartCommandResult OnStartCommand (Intent intent, StartCommandFlags flags, int startId)
         {
        _cts = new CancellationTokenSource ();
        Task.Run (() => {
                try {
                //INVOKE THE SHARED CODE
                var oBackground = new SyncingBackgroundingCode();
                oBackground.RunBackgroundingCode(_cts.Token).Wait();
            }
            catch (OperationCanceledException) 
        {

        }
        finally {
        if (_cts.IsCancellationRequested) 
        {
                var message = new CancelledTask();
        Device.BeginInvokeOnMainThread (
                                    () => MessagingCenter.Send(message, "CancelledTask")
                );
            }
            }
            }, _cts.Token);
        return StartCommandResult.Sticky;
            }


        public override void OnDestroy ()
        {
        if (_cts != null) {
            _cts.Token.ThrowIfCancellationRequested ();

        _cts.Cancel ();
            }
        base.OnDestroy ();
            }
        }

    This is in PCL:-


         public class SyncingBackgroundingCode
                {
                    public SQLiteConnection _sqlconnection;
                    SqliteCalls oSQLite = new SqliteCalls();
                ISqliteService _SqliteService;

                public SyncingBackgroundingCode(ISqliteService SqliteService)
                {
                //object is null
                }

                    public async Task RunBackgroundingCode(CancellationToken token)
                    {
                            DependencyService.Get<ISQLite>().GetConnection();

                        await Task.Run (async () => {

                            token.ThrowIfCancellationRequested();

                            if (App.oSqliteCallsMainLH != null)
                            {                 
                                App.bRunningBackgroundTask = true;

                                oSQLite = App.oSqliteCallsMainLH;
                                await Task.Run(async () =>
                                {
                                    await Task.Delay(1);
                                    oSQLite.ftnSaveOnlineModeXMLFormat("Offline", 0); 
                                    oSQLite.SyncEmployeeTableData();
                                    oSQLite.SaveOfflineAppCommentData();
                                    oSQLite.SaveOfflineAdditionToFlowData();
                                    await Task.Delay(500);

                                    var msgStopSyncBackgroundingTask = new StopSyncBackgroundingTask();
                                    MessagingCenter.Send(msgStopSyncBackgroundingTask, "StopSyncBackgroundingTask");  
                                });

                            }

                        }, token);
                    }
                }

回答1:


Unfortunately Xamarin and Xamarin Forms don't give frameworks like Prism anywhere to tie into to handle IoC scenarios. There are a couple of ways you can handle this though.

First the Container is a public property on the PrismApplication in your background service you could do something like:

public class FooBackgroundService
{
    private App _app => (App)Xamarin.Forms.Application.Current;

    private void DoFoo()
    {
        var sqlite = _app.Container.Resolve<ISQLite>();
    }
}

Another slightly more involved way would be to use the ServiceLocator pattern. You might have something like the following:

public static class Locator
{
    private static Func<Type, object> _resolver;

    public static T ResolveService<T>() => 
        (T)_resolver?.Invoke(typeof(T));

    public static void SetResolver(Func<Type, object> resolver) => 
        _resolver = resolver;
}

In your app you would then simply set the resolver. Prism actually does something similar to this with the ViewModel locator, which then allows it to inject the correct instance of the NavigationService.

public class App : PrismApplication
{
    protected override void OnInitialized()
    {
        SetServiceLocator();
        NavigationService.NavigateAsync("MainPage");
    }

    protected override void RegisterTypes()
    {
        // RegisterTypes
    }

    private void SetServiceLocator()
    {
        Locator.SetResolver(type => Container.Resolve(type, true));
    }
}

Finally your service would simply reference the Service Locator like:

public class BarBackgroundService
{
    public void DoBar()
    {
        var sqlite = Locator.ResolveService<ISQLite>();
        // do foo
    }
}


来源:https://stackoverflow.com/questions/45097342/implement-dependency-injection-in-background-services-in-xamarin-forms-using-pri

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!