xamarin在面对PCL无法实现的各平台特有功能时使用了一种叫【DependencyService】的方式来实现。它使得xamarin能像原生平台一样做平台能做到的事情!主要分四个部分
- 接口:定义功能接口在PCL类库或者共享类库
- 接口实现:各个平台实现接口功能
- 注册:各个平台实现接口的类库注册DependencyAttribute属性
- 调用:PCL类库或者共享类库调用DependencyService.Get<接口>()方法获取平台实例对象
DependencyService.cs文件的Get方法如下
1 namespace Xamarin.Forms 2 { 3 // 4 // 摘要: 5 // Static class that provides the Xamarin.Forms.DependencyService.Get{T} factory 6 // method for retrieving platform-specific implementations of the specified type 7 // T. 8 // 9 // 备注: 10 // To be added. 11 public static class DependencyService 12 { 13 // 14 // 摘要: 15 // Returns the platform-specific implementation of type T. 16 // 17 // 参数: 18 // fetchTarget: 19 // To be added. 20 // 21 // 类型参数: 22 // T: 23 // To be added. 24 // 25 // 返回结果: 26 // To be added. 27 // 28 // 备注: 29 // To be added. 30 public static T Get<T>(DependencyFetchTarget fetchTarget = DependencyFetchTarget.GlobalInstance) where T : class; 31 // 32 // 摘要: 33 // Registers the platform-specific implementation of type T. 34 // 35 // 类型参数: 36 // T: 37 // To be added. 38 // 39 // 备注: 40 // To be added. 41 public static void Register<T>() where T : class; 42 // 43 // 摘要: 44 // Registers the platform-specific implementation of type T. 45 // 46 // 类型参数: 47 // T: 48 // To be added. 49 // 50 // TImpl: 51 // To be added. 52 // 53 // 备注: 54 // To be added. 55 public static void Register<T, TImpl>() 56 where T : class 57 where TImpl : class, T; 58 } 59 }
可以看到DependencyService.cs的Get方法在默认创建的时候是使用DependencyFetchTarget.GlobalInstance,即默认是单列形式存在。在使用时需要特别注意:两个地方调用这方法的时候都时同一个实例,如果像创建新的不同实例,可以传参数为DependencyFetchTarget.NewInstance,方式如下
DependencyService.Get<IAboutRemark>(DependencyFetchTarget.NewInstance).GiveRemark();
在看注册,代码如下
1 namespace Xamarin.Forms 2 { 3 // 4 // 摘要: 5 // An attribute that indicates that the specified type provides a concrete implementation 6 // of a needed interface. 7 // 8 // 备注: 9 // To be added. 10 [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 11 public class DependencyAttribute : Attribute 12 { 13 public DependencyAttribute(Type implementorType); 14 } 15 }
通过依赖注入的方式,定义程序集属性标签。
附录下DependencyService.cs文件的Initialize方法
static void Initialize() { Assembly[] assemblies = Device.GetAssemblies(); if (Registrar.ExtraAssemblies != null) { assemblies = assemblies.Union(Registrar.ExtraAssemblies).ToArray(); } Type targetAttrType = typeof(DependencyAttribute); // Don't use LINQ for performance reasons // Naive implementation can easily take over a second to run foreach (Assembly assembly in assemblies) { Attribute[] attributes = assembly.GetCustomAttributes(targetAttrType).ToArray(); if (attributes.Length == 0) continue; foreach (DependencyAttribute attribute in attributes) { if (!DependencyTypes.Contains(attribute.Implementor)) { DependencyTypes.Add(attribute.Implementor); } } } s_initialized = true; }
从方法中可以看出DependencyService是采用遍历DependencyAttribute属性的方式来实例化对象的。