csharpshare.com
Show / Hide Table of Contents

自定义容器

Gitee仓库 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;
}
本文导航
返回顶部 ©2022-2023 csharpshare.com    冀ICP备2022026743号-1     公安备案图标 冀公网安备 13052902000206号     Icons by Icons8