无法使用autofac注册结构实例

时间:2017-04-05 07:10:48

标签: c# dependency-injection autofac

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

public static void Register(ContainerBuilder containerBuilder,
                            CancellationToken shutDownCancellationToken)
{
    containerBuilder.RegisterType<CancellationToken>();
    containerBuilder.RegisterInstance(shutDownCancellationToken);
}

我收到以下错误:

  

CancellationToken”类型必须是引用类型才能在通用类型或方法“T

中将其用作参数“RegistrationExtensions.RegisterInstance<T>(ContainerBuilder, T)

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

1 个答案:

答案 0 :(得分:9)

作为RegisterInstance约束的class方法禁止struct注册但CancellationTokenstruct这就是您收到此错误消息的原因。要绕过此约束,您可以使用Register方法注册实例。

builder.Register(_ => source.Token).As<CancellationToken>(); 

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

但为什么RegisterInstanceclass约束?

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

根据定义,struct的行为类似于副本,而不像引用。有关详细信息,请参阅Struct vs Class

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

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);
    }
}

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

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();

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