2016-11-30 234 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进行注册。你会摆脱你模块中的所有混乱。