使用Prism在Xamarin Forms中的后台服务中实现依赖项注入 [英] Implement dependency injection in background services in Xamarin Forms using Prism

查看:267
本文介绍了使用Prism在Xamarin Forms中的后台服务中实现依赖项注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在xamarin表单项目中使用了Prism.我能够在视图模型中使用依赖项注入(构造函数注入)而没有任何问题.我还利用后台服务在后台推送了长时间运行的任务如何在我的Background服务中注入依赖项?当我尝试将接口对象作为参数传递给构造函数(SyncingBackgroundingCode)时,该对象(SqliteService)为null.我已在依赖项注入容器中注册并解析了这些对象. 如何处理这种情况?有人可以提供示例或链接来实现这种情况吗?

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);
                    }
                }

推荐答案

不幸的是,Xamarin和Xamarin Forms并没有提供任何类似Prism的框架来处理IoC场景.不过,有两种方法可以解决此问题.

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.

首先,容器是您的后台服务中PrismApplication上的公共属性,您可以执行以下操作:

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>();
    }
}

另一种涉及更多的方法是使用ServiceLocator模式.您可能会有类似以下的内容:

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;
}

然后在您的应用中,只需设置解析器. Prism实际上使用ViewModel定位器执行类似的操作,然后允许它注入正确的NavigationService实例.

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
    }
}

这篇关于使用Prism在Xamarin Forms中的后台服务中实现依赖项注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆