自定义容器
Prism-Documentation-CH
2023-1-13
由于各种原因,Prism团队无法支持开发人员可能想要使用的每一个容器。但Prism会让您在使用不受官方支持或Prism库提供的容器时变得非常容易。
Prism为使用的容器提出了以下要求:
- 容器必须是可变的,以支持Prism模块化
- 容器必须支持瞬态(Transient)和单例(Singleton)注册
- 容器必须支持注册指定实例
- 容器必须支持按名称注册/解析
- 容器必须支持访问其服务注册
- 容器必须支持所有三个Prism的平台(WPF、Uno/WinUI/UWP、Xamarin.Forms)
在本主题中,我们将为Grace DI容器创建一个容器扩展。
创建一个新项目
第一步是创建一个新项目,该项目将包含DI容器扩展的代码。
dotnet new classlib
下一步,您需要添加对Prism.Core和您所选择的容器的引用
添加一个容器扩展
接下来,在你的项目中添加一个新类并实现IContainerExtension
接口。其中IContainerExtension
接口用于为最常见的注册和解析方法创建映射。
[!注意] 此处展示的实现方式并没有得到后期维护。请务必注意Prism 8的Ioc抽象与此处所示的有所不同,并且GraceIoc API中可能还会有其他的变化。这仅作为示例提供。
对于Grace DI容器,我们只需要添加这个类:
public class GraceContainerExtension : IContainerExtension<IInjectionScope>
{
public GraceContainerExtension()
: this(new DependencyInjectionContainer())
{
}
public GraceContainerExtension(IInjectionScope injectionScope)
{
Instance = injectionScope;
}
public IInjectionScope Instance { get; }
public void FinalizeExtension() { }
public IContainerRegistry Register(Type from, Type to)
{
Instance.Configure(c => c.Export(to).As(from));
return this;
}
public IContainerRegistry Register(Type from, Type to, string name)
{
Instance.Configure(c => c.Export(to).AsKeyed(from, name));
return this;
}
public IContainerRegistry RegisterInstance(Type type, object instance)
{
Instance.Configure(c => c.ExportInstance(instance).As(type));
return this;
}
public IContainerRegistry RegisterSingleton(Type from, Type to) =>
Instance.Configure(c => c.Export(to).As(from).Lifestyle.Singleton());
// NOTE: ContainerResolutionException is v8.0+
public object Resolve(Type type)
{
try
{
return Instance.Locate(type);
}
catch(Exception ex)
{
throw new ContainerResolutionException(ex);
}
}
// NOTE: ContainerResolutionException is v8.0+
public object Resolve(Type type, string name)
{
try
{
return Instance.Locate(type, withKey: name);
}
catch(Exception ex)
{
throw new ContainerResolutionException(ex);
}
}
}
[!注意] 如果使用Prism 8+的版本,您需要另外实现
IContainerInfo
接口,并且您的Resolve方法应捕获容器抛出的任何异常,并使用Prism ContainerResolutionException的方式重新抛出。
创建应用程序类
一旦我们添加了这个类,我们只需要添加如下内容来更新我们的应用程序:
namespace Prism.Grace
{
public partial class PrismApplication : PrismApplicationBase
{
protected override IContainerExtension CreateContainerExtension() => new GraceContainerExtension();
}
}
如前所述,Prism的IOC抽象仅提供最常见的功能。这意味着您可能会遇到需要直接访问底层容器的专业场景束手无策。因此为了实现更复杂的注册方式,您可以添加一个扩展方法,就像我们在容器特定包中提供的那样:
public static class ContainerExtensions
{
public static IInjectionScope GetContainer(this IContainerRegistry containerRegistry) =>
((IContainerExtension<IInjectionScope>)containerRegistry).Instance;
}