Autofac解决依赖关系

时间:2016-11-30 17:02:10

标签: c# asp.net-web-api autofac

我真的很擅长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();
    }
}

我正在努力应对不同的范围。 在我解释我的问题之前有一点背景。

每个提供商都有必需的服务,每个控制器都会注入一个或多个提供商。 每个提供商都可以有一个可选的提供商,只有在方法调用该提供商时才能解析。

我遇到的问题是我不知道如何设置它。 我打算将生命周期范围注入构造函数和方法中,解析所需的提供程序,但我已经读过这是不好的做法,而且它会创建一个新实例。我想为每个请求使用一个实例,但只有在该请求中需要它时才会使用。

我希望这是有道理的,我希望有人可以提供帮助!

1 个答案:

答案 0 :(得分:1)

IMO,你做得很好。

您需要的是依赖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注册所有服务。你可以摆脱模块中的所有混乱。