亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

您可以使用帶有標記界面的 Autofac 的 Owned 嗎?

您可以使用帶有標記界面的 Autofac 的 Owned 嗎?

C#
ibeautiful 2023-07-09 17:51:09
我想使用 Autofac 為給定工作單元創建一個或多個 WCF 通道的新實例。我想使用命令模式來表示工作單元,即給定的命令類注入它需要的通道并實現一系列相關操作。我嘗試了以下方法:interface IUnitOfWork{}class FooCall : IUnitOfWork{    readonly BarChannel _channel;    public FooCall(BarChannel channel)    {        Console.WriteLine($"FooCall({new {channel}})");        _channel = channel;    }    public string Foo()    {        return "FOO";    }}class BarChannel{    public BarChannel()    {        Console.WriteLine("BarChannel()");    }}class FooService{    Func<Owned<FooCall>> _helperFn;    public FooService(Func<Owned<FooCall>> helperFn)    {        _helperFn = helperFn;    }    public void CallFoo()    {        using (var helper = _helperFn())        {            Console.WriteLine($"CallFoo(), helper={helper}");            helper.Value.Foo();        }    }}class Program{    static void Main(string[] args)    {        var builder = new ContainerBuilder();        builder.RegisterType<BarChannel>().InstancePerOwned<IUnitOfWork>();        builder.RegisterType<FooCall>().AsImplementedInterfaces().AsSelf();        builder.RegisterType<FooService>();        using (var scope = builder.Build().BeginLifetimeScope())        {            Console.WriteLine("call 1");            scope.Resolve<FooService>().CallFoo();            Console.WriteLine("call 2");            scope.Resolve<FooService>().CallFoo();        }    }}簡而言之:服務方法創建一個擁有的工作單元;工作單元被注入了它調用的每個擁有的通道。代碼示例應顯示正在創建的兩個通道實例。除了似乎為擁有的依賴項創建的生命周期范圍僅標記為解析依賴項的類型 - 即 as FooCall,而不是 as IUnitOfWork。如果我注冊BarChannel為InstancePerOwned<FooCall>,則代碼有效;按原樣注冊為InstancePerOwned<IUnitOfWork>,它無法解析FooService,因為它找不到匹配的生命周期范圍。我是否遺漏了某些東西,或者是我想要使用 Autofac 無法實現的功能?我寧愿不必將所有 WCF 通道注冊為每個命令類的每個擁有的實例,這似乎會變得非常冗長。另一種解決方法是使用每個依賴實例并直接解析 Func,但這不會讓我說在重用通道及其之間的依賴關系的同時組成工作單元。
查看完整描述

1 回答

?
慕工程0101907

TA貢獻1887條經驗 獲得超5個贊

問題是,這InstancePerOwned<T>實際上只是 的一個特殊情況InstancePerMatchingLifetimeScope(params object[] lifetimeScopeTag),其中范圍被標記為typeof(T). 就目前情況而言,在嘗試解析時,此處提供的標記與附加到范圍的標記之間需要存在直接鏈接,該鏈接始終設置為該特定Owned<>依賴項內的任何內容的類型。此時沒有額外的邏輯來暗示類型之間的關系,它只是標簽上的直接匹配。


但是,InstancePerMatchingLifetimeScope確實允許指定多個標簽,因此可以執行以下操作:


builder.RegisterType<BarChannel>()

    .InstancePerMatchingLifetimeScope(new TypedService(typeof(FooCall)),new TypedService(typeof(AnotherUnitOfWork))); 

為了更簡潔地包裝它,您可以使用:


private static IEnumerable<Type> GetTypesImplementingInterface<TInterface>()

{

    return AppDomain.CurrentDomain.GetAssemblies()

        .SelectMany(s => s.GetTypes())

        .Where(p => typeof(TInterface).IsAssignableFrom(p));

}

然后是一個新的擴展方法:


public static class AutofacRegistrationBuilderExtensions

{

    public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerOwned<TLimit, TActivatorData, TRegistrationStyle>(

        this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> builder, IEnumerable<Type> serviceTypes)

    {

        return builder.InstancePerMatchingLifetimeScope(serviceTypes.Select(s => new TypedService(s)).ToArray());

    }

}

那么用法就是:


builder.RegisterType<BarChannel>().InstancePerOwned(GetTypesImplementingInterface<IUnitOfWork>());

我不確定最后一部分是否值得納入 Autofac 本身,但我想如果值得,那么最好將上面的兩種方法組合在一起,并從現有注冊中檢索適用的類型列表,例如類似的內容


InstancePerOwnedImplementing<TInterface>();

或者,擴展匹配范圍邏輯以在解析時檢查類型之間的關系可能會有點混亂,因為并非所有標簽都是 Type 類型。


查看完整回答
反對 回復 2023-07-09
  • 1 回答
  • 0 關注
  • 148 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號