簡體   English   中英

Autofac-注冊通用約束

[英]Autofac - Register generic constraint

我正在嘗試向Autofac注冊通用組件。 我遇到的問題與以下鏈接中的問題類似(錯誤消息相同)。 使用通用存儲庫將autofac與webapi綁定

我正在使用洋蔥架構( http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ )。 DbContext位於單獨的層中,而業務層是將獲取數據並執行與業務規則相關的各種操作的層。 上層只會知道接口IBaseDbManager。 我有一個垂直層,負責解決依賴關系。

下面的代碼和Autofac配置示例如下:

商務課程:

public class BaseDbManager<TContext> : IBaseDbManager where TContext : DbContext, IBaseContext
{
    private readonly TContext _context;

    public BaseDbManager(TContext context)
    {
        _context = context;
    }

    public Partner GetPersonInfo(Expression<Func<Person,bool>> predicate)
    {
        var person = _context.Persons.Where(predicate).FirstOrDefault();
        return person;
    }
}

業務接口:

public interface IBaseDbManager
{
    Partner GetPersonInfo(Expression<Func<Person, bool>> predicate);
}

數據庫上下文:

   [Database]
    public class BaseContext : DbContext, IBaseContext
    {
        public BaseContext()
            : base((string) ConnectionHelper.BaseConnectionString())
        {
            Database.SetInitializer<BaseContext>(null);
        }

        public virtual DbSet<Person> Persons { get; set; }
    }

上下文界面:

public interface IBaseContext
{
    DbSet<Partner> Partners { get; set; }
}

AUTOFAC模塊:

protected override void Load(ContainerBuilder builder)
{
    builder.RegisterType<BaseContext>().As<IBaseContext>().InstancePerLifetimeScope(); 
    builder.RegisterType(typeof(BaseDbManager<>)).As<IBaseDbManager>().InstancePerLifetimeScope();
}


問題在於,如果沒有無參數構造函數,Autofac將不知道如何解析IBaseDbManager。 我需要由Autofac解決TContext。 您如何配置Autofac來解決這些情況? 我嘗試注冊為泛型並且基於構造函數,但它也不起作用。 如果我將new()添加到約束中並在無參數構造函數中創建實例,則它可以工作...我不想以這種方式解決它。

我想念什么?

問題在於,如果沒有無參數構造函數,Autofac將不知道如何解析IBaseDbManager。

那不是問題。 這里的構造函數不是問題,Autofac不會對您的構造函數施加任何約束。

這里的問題是,在給定開放通用BaseDbManager<T> ,Autofac不知道要創建哪個封閉通用版本,因為給定的IBaseDbManager抽象是非通用的。 它無法為您推斷通用類型。

有幾種解決方案,但是由於應用程序中不同上下文類型的數量很可能非常有限(通常只有1個),因此在注冊中指定此上下文類型最有意義。 例如:

builder.RegisterType(typeof(BaseDbManager<BaseContext>)).As<IBaseDbManager>()
    .InstancePerLifetimeScope();

如果BaseContext是您唯一的上下文類型,則使BaseDbManager<T>為非泛型甚至更有意義,因為只有當您實際計划更改類型參數T ,使它成為泛型才有意義。

我有兩個與TContext約束匹配的對象(BaseContext和FakeBaseContext)。 BaseContext查詢數據庫,FakeBaseContext使用專門為單元測試創​​建的虛假數據。

這似乎不是擁有另一個上下文類的正當理由; 上下文是一組實體的定義; 在測試期間,您擁有相同的實體集。

在查看Autofac文檔的幾節內容后,我發現了與Steven的方法結合使用的注冊件,該注冊件使Autofact能夠正確解決依賴關系(請參見下面的鏈接):

http://docs.autofac.org/en/latest/register/parameters.html?highlight=WithParameter

我最終編碼的模塊注冊如下:

protected override void Load(ContainerBuilder builder)
{
    builder.RegisterType<BaseContext>()
           .As<IBaseContext>()
           .InstancePerLifetimeScope();

    builder.RegisterType<BaseDbManager<BaseContext>>().As<IBaseDbManager>()
           .WithParameter(new TypedParameter(typeof(BaseContext), new BaseContext()))
           .InstancePerLifetimeScope();
}

額外的反饋將不勝感激。 我將繼續重構我的代碼,因為我認為它可以改善。

暫無
暫無

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

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