无法使用autofac注册结构实例

pan*_*nis 4 c# dependency-injection autofac

我刚开始从Unity迁移到Autofac,我在尝试注册实例时遇到了问题.

public static void Register(ContainerBuilder containerBuilder,
                            CancellationToken shutDownCancellationToken)
{
    containerBuilder.RegisterType<CancellationToken>();
    containerBuilder.RegisterInstance(shutDownCancellationToken);
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

类型' CancellationToken'必须是引用类型才能T在泛型类型或方法中使用它作为参数' RegistrationExtensions.RegisterInstance<T>(ContainerBuilder, T)'

任何人都知道如何注册已经创建的结构实例?

Cyr*_*and 11

RegisterInstance作为一种方法class是禁止限制struct注册,但CancellationTokenstruct,这就是为什么你有这样的错误消息.要绕过此约束,可以使用该Register方法注册实例.

builder.Register(_ => source.Token).As<CancellationToken>(); 
Run Code Online (Sandbox Code Playgroud)

只要您的结构是不可变的,您将具有预期的行为,但如果您使用可变结构,则实例将不是共享.在你的情况下,CancellationToken是不可变的你不会有任何奇怪的副作用.


但是,为什么有RegisterInstance一个class约束?

使用该RegisterInstance方法注册实例时,预期的行为是每次注入对象时共享同一实例.

根据定义,struct行为类似于副本,而不是像引用.有关更多信息,请参阅结构与类.

想象一下,使用这个结构你有以下结构和服务:

public struct Foo
{
    public Int32 A { get; set; }
}
public class Service
{
    public Service(Foo foo)
    {
        this._foo = foo;
    }

    private Foo _foo;

    public void Set(Int32 a)
    {
        this._foo.A = a;
    }

    public void Print()
    {
        Console.WriteLine(this._foo.A);
    }
}
Run Code Online (Sandbox Code Playgroud)

以及使用这些服务的以下代码:

var builder = new ContainerBuilder();

Foo f = new Foo();
builder.Register(_ => f).As<Foo>();
builder.RegisterType<Service>();
IContainer container = builder.Build();

Service service1 = container.Resolve<Service>();
Service service2 = container.Resolve<Service>();

service1.Set(3);
service1.Print();
service2.Print();
Run Code Online (Sandbox Code Playgroud)

即使你只注册了一个实例,Foo它也会显示3和0.我认为这就是为什么RegisterInstanceclass约束的原因.