WPF的MVVM框架Stylet开发文档 14.2 StyletIoC 配置

14.2 StyletIoC 配置

在这里,您将学习如何创建一个新的 StyletIoC 容器,并在其上注册您的服务。

入门 - 建造者

要创建容器,您必须创建一个新的StyletIoCBuilder,并在其上注册您的所有服务。StyletIoCBuilder.BuildContainer()将已经被调用,所以你不需要调用它来构建你的容器。

例如:

// First, create the builder
var builder = new StyletIoCBuilder();

// Configure the builder
builder.Bind<IVehicle>().To<HotHatchback>();

// The container is then built for you

// Now you can use this to resolve instances of services
var vehicle = ioc.Get<IVehicle>();

创建类型的不同方式

如前所述,StyletIoC 的目的是接受对服务类型的请求,并使用您使用StyletIoCBuilder. 不过,它可以使用几种不同的技术来创建该实例。

类型绑定

最简单的称为“类型绑定”。你告诉它服务类型,以及实现该服务的类型,它就会自己弄清楚如何构造该类型。例如:

builder.Bind<IVehicle>().To<HotHatchback>();

这告诉 StyletIoC “每当我要求你一个IVehicle,使用适当的构造函数创建一个新的HotHatchback,并传入所有必要的依赖项”。

您当然可以将服务绑定到自身,只要该服务是具体类型即可。这称为“自我绑定”。例如:

builder.Bind<HotHatchback>().To<HotHatchback>();
// Or, more clearly:
builder.Bind<HotHatchback>().ToSelf();

这告诉 StyletIoC “每当我向你询问 一个HotHatchback时,请给我 一个HotHatchback并且它的所有依赖项都已经填充”。

如果您愿意,也可以使用非泛型重载:

builder.Bind(typeof(IVehicle)).To(typeof(HotHatchback));

工厂绑定

如果出于某种原因,您想告诉 StyletIoC_确切_如何构造您的类型,您可以将委托传递给它来调用。这称为“工厂绑定”。例如:

builder.Bind<IVehicle>().ToFactory(container => new HotHatchback());

那里的参数container是一个IContainer,如果您的构造函数需要将依赖项注入其中,您可以使用它,例如:

builder.Bind<IVehicle>().ToFactory(container => new HotHatchback(container.Get<Engine>()));

当然,自我绑定也适用于此:

builder.Bind<HotHatchback>().ToFactory(container => new HotHatchback());

实例绑定

您可以自己构造一个类型的实例并将其交给 IoC 容器。这对于配置对象之类的东西很有用。例如:

builder.Bind<IVehicle>().ToInstance(new HotHatchback());

实例绑定是自动单例的——容器不知道如何构造该类型的新实例,因此必须始终返回相同的实例。

默认情况下,IoC 容器将IDisposable在处理时处理实例类型,但您可以使用.ToInstance(foo).DisposeWithContainer(false);.

不同的范围

瞬态作用域

默认情况下,StyletIoC 会在您每次询问时创建给定类型的新实例——这称为“瞬态作用域”。看:

var car1 = ioc.Get<IVehicle>();
var car2 = ioc.Get<IVehicle>();

// The following statement will succeed.
Assert.AreNotEqual(car1, car2);

IoC 容器不会处理IDisposable瞬态类型——它不会声明对它们的所有权,也不知道何时应该处理它们。

单例作用域

但是,您也可以告诉它永远只创建一个服务实例,并在您每次询问时返回该实例。这称为“单例作用域”,如果您的应用程序确实有单例(大多数都有),这将非常有用,因为它使您免于拥有传统的单例对象,众所周知,传统的单例对象很难模拟单元测试。

builder.Bind<IConfigurationManager>().To<ConfigurationManager>().InSingletonScope();
var ioc = builder.BuildContainer();

var configManager1 = ioc.Get<IConfigurationManager>();
var configManager2 = ioc.Get<IConfigurationManager();

// The following statement will succeed.
Assert.AreEqual(configManager1, configManager2);

当然,这也适用于工厂绑定(工厂只会被调用一次,永远):

builder.Bind<IConfigurationManager>().ToFactory(container => new ConfigurationManager()).InSingletonScope();

请注意,单例的范围仅限于定义它们的绑定,请参阅:

builder.Bind<IConfigurationManager>().To<ConfigurationManager>().InSingletonScope();
builder.Bind<ConfigurationManager>().ToSelf();

var ioc = builder.BuildContainer();

var configManager1 = ioc.Get<IConfigurationManager>();
var configManager2 = ioc.Get<ConfigurationManager>();

// The following statement will succeed.
Assert.AreNotEqual(configManager1, configManager2);

如果你_真的_希望它们都返回同一个实例,你可以使用这种技术:

builder.Bind<ConfigurationManager>().And<IConfigurationManager>().To<ConfigurationManager>().InSingletonScope();

IoC 容器IDisposable在处理时会处理单例。

将多种类型绑定到单个服务

到目前为止,我们已经尝试将单一类型绑定到单一服务。但是,事情并非必须如此。您_可以_将多种类型绑定到单个服务,例如:

interface IVehicle { ... }
class HotHatchback : IVehicle { ... }
class OldBanger : IVehicle { ... }

builder.Bind<IVehicle>().To<HotHatchback>();
builder.Bind<IVehicle>().To<OldBanger>();

var ioc = builder.BuildContainer();

// This will throw an exception
ioc.Get<IVehicle>();

// This will return { new HotHatchback(), new OldBanger() }
IEnumerable<IVehicle> vehicles = ioc.GetAll<IVehicle>();

如您所见,如果您想获取项目数组,则需要使用IContainer.GetAll- 如果您尝试获取单个IVehiclewith IContainer.Get,StyletIoC 不知道要给您哪个,因此它会抛出异常。

这也适用于构造函数和参数注入,请参阅:

class Garage
{
   public Garage(IEnumerable<IVehicle> vehicles) { ... }
}

// And

class Garage
{
   [Inject]
   public IEnumerable<IVehicle> Vehicles { get; set; }
}

绑定通用类型

StyletIoC 处理绑定泛型类型(其中类型参数的确切类型是已知的)与普通类型相同,例如:

interface IValidator<T> { ... }
class IntValidator : IValidator<int> { ... }
builder.Bind<IValidator<int>>().To<IntValidator>();

interface IValidator<T> { ... }
class Validator<T> : IValidator<T> { ... }
builder.Bind<IValidator<int>>().To<Validator<int>>();

_当您想为类型参数的确切类型未知_的泛型类型创建绑定时,乐趣就开始了,例如:

interface IValidator<T> { ... }
class Validator<T> : IValidator<T> { ... }
builder.Bind(typeof(IValidator<>)).To(typeof(Validator<>));

var ioc = builder.BuildContainer();

var intValidator = ioc.Get<IValidator<int>>(); // 返回一个 Validator<int>

服务及其实现都可以有任意多的类型参数,但它们必须有相同_数量_的类型参数(如果你想通了,这是有道理的)。但是,类型参数可以以任何顺序出现:

interface ISomeInterface<T, U> { ... }
class SomeClass<U, T> : ISomeInterface<T, U> { ... }
builder.Bind(typeof(ISomeInterface<,>)).To(typeof(SomeClass<,>));

StyletIoC 不考虑类型约束 - 如果您有一个interface IMyInterface<T> where T : class并请求一个IMyInterface<int>,您将得到一个异常。

自动绑定

StyletIoC 能够自动为您创建绑定。

自动绑定所有具体类型

自动绑定意味着如果您请求一个尚未在 Stylet 中注册的具体类型,Stylet 将尝试将其构造为您的瞬态实例。它仅适用于您指定的程序集中的类型:那些在中的类型StyletIoCBuilder.Assemblies,以及您传递给该Autobind方法的任何程序集中的类型。

请注意,显式绑定始终优先于自动绑定。

将 mscorlib 等程序集传递给 Autobind 是个坏主意,否则 Stylet 将尝试实例化 System.String 等类型。

builder.Autobind();

这在 MVVM 应用程序中很有用,因为它允许 StyletIoC 解析您的任何 ViewModel。Stylet 引导程序调用 Autobind(),这意味着默认情况下启用自动绑定。

将服务绑定到所有实现

您还可以将服务绑定到实现它的所有类型,例如:

interface IVehicle { ... }
class HotHatchback : IVehicle { ... }
class OldBanger : IVehicle { ... }

builder.Bind<IVehicle>().ToAllImplementations();

var ioc = builder.BuildContainer();

IEnumerable<IVehicle> vehicles = ioc.GetAll<IVehicle>(); // Returns { new HotHatchback(), new OldBanger() }

还有一些重载允许您指定要搜索的程序集。

这本身就很有用(想想找到所有插件),但在与未绑定的泛型结合使用时特别有用。例如:

interface IValidator<T> { ... }
class IntValidator : IValidator<int> { ... }
class StringValidator : IValidator<string> { ... }

builder.Bind(typeof(IValidator<>)).ToAllImplementations();

var ioc = builder.BuildContainer();

var intValidator = ioc.Get<IValidator<int>>(); // Returns an IntValidator
var stringValidator = ioc.Get<IValidator<string>>(); // Returns a StringValidator

如果您想要更复杂的绑定规则,StyletIoC 不会为您提供 API - 您自己几乎不需要付出任何努力,提供 API 只会增加很多复杂性而收效甚微。

但是,StyletIoC 确实在 Type 上定义了几个扩展方法,这可能会让您的生活更轻松:

// 返回所有基础类型
someType.GetBaseTypes();

// 返回所有基础类型和接口
someType.GetBaseTypesAndInterfaces();

// 如果 someType 实现了 someServiceType,则返回 true
someType.Implements(someServiceType)
// 还考虑了泛型——所以这是真的:
typeof(Validator<int>>.Implements(typeof(IValidator<>));

项目原地址:https://github.com/canton7/Stylet
当前文档原地址:https://github.com/canton7/Stylet/wiki/StyletIoC-Configuration

上一节:WPF的MVVM框架Stylet开发文档 4.1 StyletIoC 简介
下一节:WPF的MVVM框架Stylet开发文档 14.3 StyletIoC 注入

上一篇:WPF的MVVM框架Stylet开发文档 13.验证模型基类ValidatingModelBase
下一篇:WPF的MVVM框架Stylet开发文档 15. 视图管理器 The ViewManager

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值