我真的很擅长autofac并遇到问题。 我正在使用Web API,我已经设置了我的模块:
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();
}
}
我正在努力应对不同的范围。 在我解释我的问题之前有一点背景。
每个提供商都有必需的服务,每个控制器都会注入一个或多个提供商。 每个提供商都可以有一个可选的提供商,只有在方法调用该提供商时才能解析。
我遇到的问题是我不知道如何设置它。 我打算将生命周期范围注入构造函数和方法中,解析所需的提供程序,但我已经读过这是不好的做法,而且它会创建一个新实例。我想为每个请求使用一个实例,但只有在该请求中需要它时才会使用。
我希望这是有道理的,我希望有人可以提供帮助!
答案 0 :(得分:1)
IMO,你做得很好。
您需要的是依赖Func<Provider>
。当您向Autofac询问Func<>
时,它会返回一个工厂方法,而不是.Resolve<Provider>
。
你可以这样写:
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 Scanning和AsImplementedInterfaces
注册所有服务。你可以摆脱模块中的所有混乱。