2016-11-30 341 views
0

我對autofac非常陌生,遇到問題。 我使用的Web API。我將我的模塊像這樣:Autofac解決依賴關係

public class CormarModule : Module 
{ 


    // Fields 
    private readonly string _connectionStringName; 
    private readonly connectionType _connection; 

    /// <summary> 
    /// Default constructor 
    /// </summary> 
    public CormarModule() { 
     _connectionStringName = ConfigurationManager.AppSettings["ConnectionStringName"]; 
     _connection = _connectionStringName.ToUpper().Contains("LIVE") ? connectionType.Live : connectionType.Test; 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 

     // Singletons 
     builder.RegisterType<DatabaseContext>().As<DatabaseContext>().SingleInstance(); 
     builder.RegisterType<UnitOfWork<DatabaseContext>>().As<IUnitOfWork>().SingleInstance(); 
     builder.Register(c => new OracleUnitOfWork(_connectionStringName)).As<IOracleUnitOfWork>().SingleInstance(); 
     builder.Register(c => new AdvancedEncryptionStandardProvider(ConfigurationManager.AppSettings["rm:key"], ConfigurationManager.AppSettings["rm:secret"])).As<IAdvancedEncryptionStandardProvider>().SingleInstance(); 

     // Register our services   
     builder.RegisterType<AccountService>().As<IAccountService>(); 
     builder.RegisterType<DeliveryInformationService>().As<IDeliveryInformationService>(); 
     builder.RegisterType<EmailService>().As<IEmailService>(); 
     builder.RegisterType<LogService>().As<ILogService>(); 
     builder.RegisterType<OrderService>().As<IOrderService>(); 
     builder.RegisterType<OrderLineService>().As<IOrderLineService>(); 
     builder.RegisterType<PaymentHistoryService>().As<IPaymentHistoryService>(); 
     builder.RegisterType<PrincipleProvider>().As<IPrincipleProvider>(); 
     builder.RegisterType<ProductService>().As<IProductService>(); 
     builder.RegisterType<RefreshTokenService>().As<IRefreshTokenService>(); 
     builder.RegisterType<StockService>().As<IStockService>(); 
     builder.Register(c => new UserStore<User>(c.Resolve<DatabaseContext>())).As<IUserStore<User>>(); 

     // Single instance 
     builder.RegisterType<OAuthProvider>().As<OAuthProvider>(); 
     builder.RegisterType<LogProvider>().As<ILogProvider>(); 
     builder.RegisterType<RefreshTokenProvider>().As<IAuthenticationTokenProvider>(); 
     builder.Register(c => new SendGridProvider(c.Resolve<IUnitOfWork>(), c.Resolve<IEmailService>(), ConfigurationManager.AppSettings["SendGridApiKey"])).As<ISendGridProvider>(); 
     builder.Register(c => new UserProvider(_connectionStringName, c.Resolve<IUserStore<User>>(), c.Resolve<IAdvancedEncryptionStandardProvider>(), c.Resolve<ISendGridProvider>())).As<IUserProvider>(); 

     // Per request 
     builder.RegisterType<DeliveryInformationProvider>().As<IDeliveryInformationProvider>().InstancePerRequest(); 
     builder.RegisterType<JournalProvider>().As<IJournalProvider>().InstancePerRequest(); 
     builder.RegisterType<StockProvider>().As<IStockProvider>().PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies).InstancePerRequest(); 

     builder.Register(c => new AccountProvider(_connection, c.Resolve<IAccountService>(), c.Resolve<IPrincipleProvider>(), c.Resolve<IAdvancedEncryptionStandardProvider>(), c.Resolve<IPaymentHistoryService>())).As<IAccountProvider>().InstancePerRequest(); 
     builder.Register(c => new ProductProvider(_connection, c.Resolve<IProductService>())).As<IProductProvider>().InstancePerRequest(); 
     builder.Register(c => new OrderProvider(_connection, c.Resolve<IOrderService>(), c.Resolve<IPrincipleProvider>(), c.Resolve<IAdvancedEncryptionStandardProvider>())).As<IOrderProvider>().PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies).InstancePerRequest(); 
     builder.Register(c => new OrderLineProvider(_connection, c.Resolve<IOrderLineService>(), c.Resolve<IPrincipleProvider>(), c.Resolve<IAdvancedEncryptionStandardProvider>())).As<IOrderLineProvider>().InstancePerRequest(); 
    } 
} 

我與不同的範圍掙扎。 我解釋我的問題之前有一點背景。

每個提供商具有所需服務並且每個控制器具有一個或多個提供者注入。 每個供應商可以有一個可選的供應商應該只有當方法調用該供應商時才能解決。

我有的問題是我不知道如何設置。 我打算將生命期範圍注入構造函數和方法中,解決所需的提供程序,但我已經讀過這是不好的做法,再加上它會創建一個新實例。我想爲每個請求使用一個實例,但只有在該請求中需要時才需要。

我希望這是有道理的,我希望有人能幫助!

回答

1

海事組織,你做得很好。

你需要的是取決於對Func<Provider>的依賴。當你問Autofac一個Func<>它會返回一個工廠方法,將被調用,而不是.Resolve<Provider>

請參閱herehere的文檔。

你可以寫這樣說:

private OptionalProvider _instance; 
private Func<OptionalProvider> _providerGetter; 

public OptionalProvider Prov 
{ 
    get { return _instance ?? (_instance = _providerGetter()); } 
} 

public MyProvider(Func<OptionalProvider> getter) 
{ 
    _providerGetter = getter; 
} 

public void MethodRequiringOptionalProvider() 
{ 
    // just use property Prov and let Autofac handle the rest 
} 

另一個建議:不是直接注射的_connection字符串參數,只需要創建一個CormarConfig類,與.RegisterInstance註冊到存儲所有的配置選項。 通過這種方式,您只需撥打RegisterType並讓Autofac解析所有類型參數(即可清除那些難看的Resolve調用)。

如果您的所有服務都從一個共同的祖先繼承或實現一個通用接口,則可以通過Assembly ScanningAsImplementedInterfaces進行註冊。你會擺脫你模塊中的所有混亂。