簡體   English   中英

C#,Autofac:Register<> 中未提供 NamedParameter

[英]C#, Autofac: NamedParameter is not provided in Register<>

我目前正在嘗試一些 autofac 功能,並且正在努力使用 NamedParameter。

我創建了一個非常簡單的示例,其中IFooHappyFooSadFoo實現。 IFooUser在構造函數中需要一個IFoo對象,並使用它向控制台打印一些東西。

下面的代碼顯示了我如何嘗試構建一個IFooUser對象,該對象將使用基於“分數”值的IFoo對象。

        var builder = new ContainerBuilder();

        builder.RegisterType<NormalFooUser>().As<IFooUser>();

        builder.Register<IFoo>((context, parameters) =>
        {
            var score = parameters.Named<int>("score"); // ! Exception !
            if (score >= 100)
            {
                return new HappyFoo();
            } 
            return new SadFoo();
        });

        var container = builder.Build();

        using (var scope = container.BeginLifetimeScope())
        {
            scope.Resolve<IFooUser>(new NamedParameter("score", 90)).useFoo();
        }

不幸的是,當我執行此代碼時, parameters序列不包含任何值 => 異常! 當我決定使用IFoo一切正常:

       scope.Resolve<IFoo>(new NamedParameter("score", 90)).foo(); // Works

但這不是我想做的。 所以我想知道怎樣才能構建一個IFooUserIFoo對應與NamedParameter“分數”的對象。

完整的代碼示例可以在這里找到作為要點

謝謝。

NamedParameter旨在配置請求的組件而不是整個依賴圖,該參數不會在整個注冊過程中傳播,它不是上下文參數。

如果你想要一個上下文,你可以實現這樣一個組件來存儲一些屬性。

// interface 
interface IContext {
    T Get<T>(String name); 
    void Set<T>(String name, T value); 
}

// registration 
builder.RegisterType<FooContext>().As<IContext>();
builder.Register<IFoo>(c =>
{
    var score = c.Resolve<IContext>().Get<Int32>("score"); 
    if (score >= 100)
    {
        return new HappyFoo();
    }
    return new SadFoo();
});


// usage 
using (ILifetimeScope scope = container.BeginLifetimeScope())
{
    scope.Resolve<IContext>().Set("score", 90); 
    scope.Resolve<IFooUser>().useFoo();
}

這種方法的優點是您可以在當前生命周期范圍內隨時設置上下文屬性。 您還可以想象沒有Set方法的實現,它將根據您想要的任何內容檢索值。

另一種做同樣事情的方法是使用Func<Int32, IFoo>依賴項和TypedAs方法

builder.Register<IFoo>((c, p) =>
{
    Int32 score = p.TypedAs<Int32>(); 
    if (score >= 100)
    {
        return new HappyFoo();
    }
    return new SadFoo();
});

當然你必須改變IFooUser接口和實現

public class NormalFooUser : IFooUser
{
    private readonly Func<Int32, IFoo> _fooBuilder;

    public NormalFooUser(Func<Int32,IFoo> fooBuilder)
    {
        _fooBuilder = fooBuilder;
    }

    public void useFoo(Int32 score)
    {
        _fooBuilder(score).foo();
    }
}
scope.Resolve<IFooUser>(new NamedParameter("score", 90))

告訴 Autofac 它應該使用參數score來創建注冊為IFooUser的實例,但實際上它不需要它 - 它的依賴項IFoo需要它。 Autofac 不會自動將這些參數傳遞給類型的依賴項,您需要自己完成,只需在IFooUser注冊時傳遞參數

builder.Register((c, p) => new NormalFooUser(c.Resolve<IFoo>(p))).As<IFooUser>();

此代碼段傳遞用於解析IFooUser所有參數,您只能將其限制為這些必需的

builder.Register((c, p) => new NormalFooUser(c.Resolve<IFoo>(new NamedParameter("score", p.Named<int>("score"))))).As<IFooUser>();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM