Advertisement
Shimmy

Untitled

Feb 23rd, 2017
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.74 KB | None | 0 0
  1. I don't know if I'm doing wrong, but I using DI to inject a global exception notifier to the appropriate target framework.
  2. I'm using Prism, and since Xamarin's `DependencyService` doesn't offer adding instances, I'm achieving this with reflection.
  3.  
  4. So I've added this function that I call on the `RegisterTypes` of the portable app:
  5.  
  6.    public static class UnityContainerExtensions
  7.    {
  8.      public static void RegisterWithXamarin(this IUnityContainer container)
  9.      {
  10.        var depType = typeof(DependencyService);
  11.        var depTypeInfo = depType.GetTypeInfo();
  12.    
  13.        depTypeInfo.DeclaredMethods.Single(mi => mi.Name == "Initialize").Invoke(null, null);
  14.    
  15.        var dependencyTypes = (List<Type>)depTypeInfo.DeclaredFields.Single(fi => fi.Name == "DependencyTypes").GetValue(null);
  16.        if (dependencyTypes.Contains(depType))
  17.          return;
  18.    
  19.        var targetType = typeof(IUnityContainer);
  20.        var implementorType = container.GetType();
  21.                
  22.        dependencyTypes.Add(targetType);
  23.    
  24.        var nested = depTypeInfo.DeclaredNestedTypes.Single(t => t.Name == "DependencyData");
  25.        var dependencyData = Activator.CreateInstance(nested.AsType());
  26.        nested.DeclaredProperties.Single(p => p.Name == "ImplementorType").SetValue(dependencyData, implementorType);
  27.        nested.DeclaredProperties.Single(p => p.Name == "GlobalInstance").SetValue(dependencyData, container);
  28.    
  29.        var dependencyImplementations = depTypeInfo.DeclaredFields.Single(fi => fi.Name == "DependencyImplementations").GetValue(null);
  30.        dependencyImplementations.GetType().GetRuntimeProperty("Item").SetValue(dependencyImplementations, dependencyData, new[] { targetType });      
  31.      }
  32.    }
  33.    
  34. Now  I'm adding another couple of classes to the portable app:
  35.  
  36.     public class GlobalExceptionHandler
  37.     {
  38.       public GlobalExceptionHandler(Action<GlobalExceptionData> handler)
  39.       {
  40.         ExceptionHandler = handler;
  41.       }
  42.    
  43.       public void OnCompleted() { }
  44.       public void OnError(Exception error) { }
  45.       public void OnNext(GlobalExceptionData data) =>
  46.         ExceptionHandler?.Invoke(data);
  47.    
  48.       public Action<GlobalExceptionData> ExceptionHandler { get; }
  49.     }
  50.    
  51.     public class GlobalExceptionData
  52.     {
  53.       public GlobalExceptionData(Exception exception, bool handled = false, string message = null)
  54.       {
  55.         Exception = exception;
  56.         Handled = handled;
  57.         Message = message ?? exception.Message;
  58.       }
  59.    
  60.       public Exception Exception { get; }
  61.       public bool Handled { get; set; }
  62.       public string Message { get; set; }
  63.     }
  64.    
  65. In the target-specific project I'm notifying the `GlobalExceptionHandler` (UWP in this example), _App.xaml.cs_ file:
  66.  
  67.    public App()
  68.    {
  69.      this.InitializeComponent();
  70.      this.Suspending += OnSuspending;
  71.    
  72.      UnhandledException += App_UnhandledException;
  73.    }
  74.    
  75.    private void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
  76.    {
  77.      var unityContainer = Xamarin.Forms.DependencyService.Get<IUnityContainer>();
  78.      var exceptionHandler = unityContainer.Resolve<GlobalExceptionHandler>();
  79.      var data = new GlobalExceptionData(e.Exception, e.Handled, e.Message);
  80.      exceptionHandler.OnNext(data);
  81.      e.Handled = data.Handled;
  82.    }
  83.    
  84. Make sure you call these two methods in the `RegisterTypes` method in the portable app:
  85.  
  86.    protected override void RegisterTypes()
  87.    {
  88.      Container.RegisterWithXamarin();
  89.      Container.RegisterType<GlobalExceptionHandler>(new InjectionFactory(c => new GlobalExceptionHandler(OnGlobalException)));
  90.    }
  91.  
  92. Although this solution is prism specific it should be easy to adapt it to no-prism.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement