新文章 网摘 文章 随笔 日记

Android中的依赖注入容器– Xamarin

这篇文章非常有趣,因为我们将继续努力,

  1. 使用Xamarin兼容的依赖项注入(IoC)容器来管理所有依赖项
  2. 使用可移植类库在每个Android应用程序中重用我们的代码
  3. 构建自定义列表适配器以显示我们的产品列表

所以,让我们开始吧!

这是我们应用程序的架构,

建立一个可移植的类库

一个便携式类库(PCL)允许我们编写代码,并生成可跨多个平台,包括共享的库Xamarin.iOSXamarin.AndroidWindows手机

让我们创建一个新的Portable Class Library项目,

 

举报此广告
举报此广告

 

让我们在此共享代码库中编写一些代码,

产品模型类,产品服务接口及其实现如下,

1个
2
3
4
5
6
7
public class Product
 {
 public int Id { get; set; }
 public string Name { get; set; }
 public string Description { get; set; }
 public decimal Price { get; set; }
 }

 

举报此广告
举报此广告

 

现在让我们写产品服务的抽象和实现,

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public interface IProductService
 {
 IEnumerable<Product> GetAll();
 }
public class ProductService : IProductService
 {
 public IEnumerable<Product> GetAll()
 {
 return new List<Product>
 {
 new Product {
 Id =1,
 Name = "Google Android 2.2",
 Description = "Products's description.",
 },
 new Product {
 Id =2,
 Name = "Apple iPad",
 Description = "Products's description.",
 },
 new Product {
 Id =3,
 Name = "Amazon Kindle (third-generation)",
 Description = "Products's description.",
 },
 new Product {
 Id =4,
 Name = "Netflix",
 Description = "Products's description.",
 },
 new Product {
 Id =5,
 Name = "Samsung Galaxy Tab",
 Description = "Products's description.",
 }, 
 };
 }
 }
</pre>
<pre>

创建一个Android应用程序

现在,我们创建一个Android应用程序项目,参考我们的可移植类库,并设置基本的基础架构以显示产品列表,

 

举报此广告
 
举报此广告

 

要显示产品列表,我们将ListView控件添加到/ Resources / layout / Main.axml文件中,如下所示,

1个
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <ListView
 android:minWidth="25px"
 android:minHeight="25px"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:id="@+id/productListView" />
</LinearLayout>

让我们创建一个ProductListAdapter(适配器)类,我们可以使用该类将产品服务器中的产品列表附加到android视图中的ListView上。(尽管我们可以使用Android嵌入式列表资源,但是编写我们的自定义列表适配器可以进行更多的自定义)

让我们在Adapters / ProductListAdapter.cs创建一个名为“ ProductListAdapter.cs ” 的新类

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class ProductListAdapter : BaseAdapter<Product>
 {
 private readonly List<Product> _productsList;
 private readonly Activity _context;
 
 public ProductListAdapter()
 {
  
 }
 
 public ProductListAdapter(Activity context, List<Product> products)
 {
 _context = context;
 _productsList = products;
 }
 
 //Indexer to retrun a product item on a particular position
 public override Product this[int position]
 {
 get { return _productsList[position]; }
 }
 
 //Total number of items in the list
 public override int Count
 {
 get { return _productsList.Count; }
 }
 
 //returns item id, we're simply returning the position
 public override long GetItemId(int position)
 {
 return position;
 }
 
 //Returns row view in the list
 //There can be hundreds of rows to show however, android shows only displayable rows on the screen
 //Used rows and go off-display are stored in a backyard for later use
 public override View GetView(int position, View convertView, ViewGroup parent)
 {
 var item = _productsList[position];
 
 //if its a new row, create a row item
 if (convertView == null)
 {
 //Inflating is the process of generating objects based on the XML
 //So, its passing the XML and instantiating the objects
 
 //Android.Resource.Layout.SimpleListItem1 is a baked-in resource(not in our project)
 convertView = _context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
 }
 
 convertView.FindViewById<TextView>(Android.Resource.Id.Text1).Text = item.Name;
 
 return convertView;
 }
 }

 

举报此广告
举报此广告

 

我们将在以下每个Android应用程序Main.axml文件和ProductListAdapter中使用相同的ListView 

现在,是时候在列表中显示产品了。通过管理依赖关系,让我们使用可在移动应用程序中使用的各种依赖关系注入容器。

统一

让我们安装Unity IoC容器软件包,

我们希望在整个应用程序中全局使用IoC容器,并确保在应用程序启动时以及激发任何活动之前加载它。为此,我们可以创建一个新类,该新类应该是Android.App.Application的子类并且此子类应使用[Application]属性修饰,也请注意,我们的应用程序只能具有一个具有[Application]属性的类。

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
//Wiring up the container in App class
 [Application]//Application attribute can be used only once throughout the application
 public class App : Application
 {
 public App(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
 {
 
 }
 
 public override void OnCreate()
 {
 Initialize();
 
 base.OnCreate();
 }
 
 public static UnityContainer Container { get; set; }
 
 private static void Initialize()
 {
 App.Container = new UnityContainer();
 
 App.Container.RegisterType<IProductService, ProductService>();
 App.Container.RegisterType<BaseAdapter<Product>, ProductListAdapter>();
 }
 }

 

举报此广告
举报此广告

 

使用Unity IoC容器解析ProductViewModel依赖项。并在Unity中传递构造函数参数以解决ProductListAdapter依赖性。

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[Activity(Label = "Unity Demo - Products List", MainLauncher = true, Icon = "@drawable/icon")]
 public class MainActivity : Activity
 {
 private ListView _productsListView;
 
 protected override void OnCreate(Bundle bundle)
 {
 base.OnCreate(bundle);
 
 // Set our view from the "main" layout resource
 SetContentView(Resource.Layout.Main);
 
 //initialize controls
 SetupControls();
 
 //display products
 DisplayProducts();
 }
 
 private void SetupControls()
 {
 _productsListView = FindViewById<ListView>(Resource.Id.productListView);
 
 }
 
 private void DisplayProducts()
 {
 var viewModel = App.Container.Resolve(typeof(ProductViewModel), "productViewModel") as ProductViewModel;
 
 var productsList = new List<Product>();
 if (viewModel != null)
 {
 productsList = viewModel.ProductList.ToList();
 }
 
 //override constructor parameters
 //passing current ativity (this), and products list to the ProductsListAdapter
 var param = new ParameterOverrides { { "context", this }, { "products", productsList } };
 
 var productListAdapter = App.Container.Resolve<ProductListAdapter>(param);
 
 //attach the adapter to the listview
 _productsListView.Adapter = productListAdapter;
 }
 }

 

举报此广告
举报此广告

 

现在,我们构建并运行该应用程序,然后在Android模拟器中看到如下输出,

 

微小的

让我们创建一个新的Android项目以使用TinyIoC容器,并安装TinyIoC NuGet软件包,

就像上面的项目一样,我们需要使用TinyIoC特定的实现编写  App.cs类,

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
[Application]
 public class App : Application
 {
 public App(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
 {
 
 }
 
 public override void OnCreate()
 {
 Initialize();
 
 base.OnCreate();
 }
 
 private static void Initialize()
 {
 //TinyIoC.TinyIoCContainer.Current.AutoRegister() also works
 //but its performance hit on everytime application starts
 
 var container = TinyIoC.TinyIoCContainer.Current;
 
 container.Register<IProductService, ProductService>();
 container.Register<BaseAdapter<Product>, ProductListAdapter>();
 }
 }

 

举报此广告
举报此广告

 

使用TinyIoC容器解析ProductViewModel依赖项。并在TinyIoC中传递构造函数参数以解决ProductListAdapter依赖性。

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[Activity(Label = "TinyIoC Demo - Products List", MainLauncher = true, Icon = "@drawable/icon")]
 public class MainActivity : Activity
 {
 private ListView _productsListView;
 
 protected override void OnCreate(Bundle bundle)
 {
 base.OnCreate(bundle);
 
 // Set our view from the "main" layout resource
 SetContentView(Resource.Layout.Main);
 
 //initialize controls
 SetupControls();
 
 //display products
 DisplayProducts();
 }
 
 private void SetupControls()
 {
 _productsListView = FindViewById<ListView>(Resource.Id.productListView);
 }
 
 private void DisplayProducts()
 {
 var viewModel = TinyIoC.TinyIoCContainer.Current.Resolve<ProductViewModel>();
 var productsList = new List<Product>();
 if (viewModel != null)
 {
 productsList = viewModel.ProductList.ToList();
 }
 
 //resolving constructor parameters
 //override constructor parameters
 //passing current ativity (this), and products list to the ProductsListAdapter
 var param = new TinyIoC.NamedParameterOverloads { { "context", this }, { "products", productsList } };
 
 var productListAdapter = TinyIoC.TinyIoCContainer.Current.Resolve<ProductListAdapter>(param);
 
 //attach the adapter to the listview
 _productsListView.Adapter = productListAdapter;
 }
 }

 

举报此广告
举报此广告

 

在构建和运行应用程序时,它将显示相同的输出。

Ninject

让我们创建一个新的Android项目以使用Portable Ninject容器,并安装Portable Ninject NuGet软件包,

让我们为依赖项绑定创建一个名为“ NinjectCustomModule”的新类,

1个
2
3
4
5
6
7
8
public class NinjectCustomModule : NinjectModule
 {
 public override void Load()
 {
 this.Bind<IProductService>().To<ProductService>();
 this.Bind<BaseAdapter<Product>>().To<ProductListAdapter>();
 }
 }

让我们为特定于Ninject的实现编写App.cs类,

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
[Application]
 public class App : Application
 {
 public static IKernel Container { get; set; }
 public App(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
 {
 
}
 
public override void OnCreate()
 {
 Initialize();
 
base.OnCreate();
 }
 
private static void Initialize()
 {
 var kernel = new StandardKernel(new NinjectCustomModule());
 
App.Container = kernel;
 }
 }

 

举报此广告
举报此广告

 

使用Ninject IoC容器可解决ProductViewModel依赖项。并在Ninject中传递构造函数参数以解决ProductListAdapter依赖性。

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[Activity(Label = "Ninject Demo - Products List", MainLauncher = true, Icon = "@drawable/icon")]
 public class MainActivity : Activity
 {
 private ListView _productsListView;
 
 protected override void OnCreate(Bundle bundle)
 {
 base.OnCreate(bundle);
 
 // Set our view from the "main" layout resource
 SetContentView(Resource.Layout.Main);
 
 //initialize controls
 SetupControls();
 
 //display products
 DisplayProducts();
 }
 
 private void SetupControls()
 {
 _productsListView = FindViewById<ListView>(Resource.Id.productListView);
 }
 
 private void DisplayProducts()
 {
 //Resolving dependency in Ninject
 var viewModel = App.Container.Get<ProductViewModel>();
 var productsList = new List<Product>();
 if (viewModel != null)
 {
 productsList = viewModel.ProductList.ToList();
 }
 
 //passing constructor arguments in Ninject
 var contextArg = new ConstructorArgument("context", this);
 var productsArg = new ConstructorArgument("products", productsList);
 var productListAdapter = App.Container.Get<ProductListAdapter>(contextArg, productsArg);
  
 _productsListView.Adapter = productListAdapter;
 }
 }

 

举报此广告
举报此广告

 

在构建和运行应用程序时,它将显示相同的输出。

Autofac

让我们创建一个新的Android项目以使用Autofac IoC容器,并安装Autofac NuGet软件包,

让我们为Autofac的特定实现编写App.cs类,

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
[Application]
 public class App : Application
 {
 public static IContainer Container { get; set; }
 
 public App(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
 {
 
 }
 
 public override void OnCreate()
 {
 Initialize();
 
 base.OnCreate();
 }
 
 private static void Initialize()
 {
 var builder = new ContainerBuilder();
 
 builder.RegisterInstance(new ProductService()).As<IProductService>();
 builder.RegisterType<ProductViewModel>();
 
 builder.RegisterInstance(new ProductListAdapter()).As<BaseAdapter<Product>>();
 builder.RegisterType<ProductListAdapter>();
 
 App.Container = builder.Build();
 }
 }

 

举报此广告
举报此广告

 

现在在MainActivity中,可以使用Autofac IoC容器解析ProductViewModel依赖项。并在Autofac中传递构造函数参数以解决ProductListAdapter依赖性。

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
[Activity(Label = "Autofac Demo - Products List", MainLauncher = true, Icon = "@drawable/icon")]
 public class MainActivity : Activity
 {
 private ListView _productsListView;
 
 protected override void OnCreate(Bundle bundle)
 {
 base.OnCreate(bundle);
 
 // Set our view from the "main" layout resource
 SetContentView(Resource.Layout.Main);
 
 //initialize controls
 SetupControls();
 
 //display products
 DisplayProducts();
 }
 
 private void SetupControls()
 {
 _productsListView = FindViewById<ListView>(Resource.Id.productListView);
 }
 
 private void DisplayProducts()
 {
 ProductViewModel viewModel;
 using (var scope = App.Container.BeginLifetimeScope())
 {
 viewModel = App.Container.Resolve<ProductViewModel>();
 }
 
 var productsList = new List<Product>();
 if (viewModel != null)
 {
 productsList = viewModel.ProductList.ToList();
 }
 
 ProductListAdapter productListAdapter;
 using (var scope = App.Container.BeginLifetimeScope())
 {
 productListAdapter = App.Container.Resolve<ProductListAdapter>(
 new NamedParameter("context", this),
 new NamedParameter("products", productsList)
 );
 }
 
 //attach the adapter to the listview
 _productsListView.Adapter = productListAdapter;
 }
 }

 

举报此广告
举报此广告

 

在构建和运行应用程序时,它将显示相同的输出。

 

源代码= Xamarin.Android.IoC

 

https://mwasimse.wordpress.com/2016/06/30/dependency-injection-containers-in-xamarin/

posted @ 2020-08-24 10:24  岭南春  阅读(218)  评论(0)    收藏  举报