1

私のxamarinフォームプロジェクトでプリズムを使用しています。ビューモデルに依存性注入(コンストラクタインジェクション)を問題なく使用できました。 (バックグラウンドで長時間実行されるタスクをプッシュするバックグラウンドサービス)バックグラウンドサービスに依存関係を注入する方法インターフェイスオブジェクトをコンストラクタ(SyncingBackgroundingCode)のパラメータとして渡すと、オブジェクト(SqliteService)がnullになります。依存性注入コンテナ内のオブジェクトを登録して解決しました。 このケースを処理するにはどうすればよいですか?このシナリオを実装するための例やリンクを誰かから提供できますか?プリマを使用したXamarinフォームの依存サービスの実装

これは、依存関係注入を実装しようとしているコードの一部です。

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

おそらくDependencyService.Get ()コンテナは、サービスを登録する機会を持って前に呼び出された可能性があります。正しい順序でトリガーされていることを確認してください。それ以外の場合は、サービスが解決されない理由はありません。また、アセンブリに[assembly:Dependency(typeof(SQLitService))]を使用してサービスを登録することをお勧めします。これにより、コードが解決される前にサービスが常に登録されます。 –

答えて

2

残念ながらXamarinとXamarinフォームは、IoCのシナリオを処理するために結びつけるためにどこでもプリズムのようなフレームワークを与えることはありません。あなたがこれを扱うことができる方法のいくつかがあります。別の少しより複雑な方法は、のServiceLocatorパターンを用いることであろう

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

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

第一の容器はあなたのような何かを行うことができ、あなたのバックグラウンドサービスでPrismApplicationのパブリックプロパティです。あなたは、単にリゾルバを設定しますあなたのアプリで

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の正しいインスタンスを挿入できるようにします。

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

は、最後にあなたのサービスは、単にのようなサービスロケータを参照します:

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

ありがとうございます。最初のアプローチは私のために働いた – Debasish

関連する問題