简体   繁体   English

Autofac解决依赖项

[英]Autofac resolving dependencies

I am really new to autofac and having issues. 我对autofac真的很陌生,并且遇到了问题。 I am using Web API and I have set my module up like this: 我正在使用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();
    }
}

I am struggling with the different scopes. 我正在努力应对不同的范围。 A little background before I explain my issue. 在我解释我的问题之前需要一些背景知识。

Each Provider has a required Service and each Controller has one or more Providers injected. 每个提供程序都有所需的服务 ,每个控制器都有一个或多个注入的提供程序 Each Provider could have an optional Provider which should only be resolved when a method invokes that provider. 每个提供程序都可以有一个可选的提供程序 ,仅当方法调用该提供程序时才应解析该提供程序。

The problem I have is I don't know how to set that up. 我的问题是我不知道该如何设置。 I was going to inject the lifetime scope into the constructor and in the method, resolve the required Provider , but I have read this is bad practice, plus it would create a new instance. 我打算将生存期范围注入到构造函数中,并在方法中解析所需的Provider ,但是我已经读到这是一种不好的做法,而且还会创建一个新实例。 I would like to use one instance per request, but only if it is need in that request. 我想为每个请求使用一个实例,但前提是该请求中需要它。

I hope that makes sense and I hope someone can help! 我希望这是有道理的,希望有人能提供帮助!

IMO, you're doing pretty good. 海事组织,你做得很好。

What you need is to take a dependency on a Func<Provider> . 您需要依赖于Func<Provider> When you ask Autofac a Func<> it returns a factory method, to be called instead of .Resolve<Provider> . 当您要求Autofac Func<>它将返回一个工厂方法,而不是.Resolve<Provider>来调用。

See here and here for documentation. 请参阅此处此处的文档。

You can write it this way: 您可以这样写:

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
}

Another suggestion: instead of injecting directly the _connection string parameter, just create a CormarConfig class, to be registered with .RegisterInstance to store all your configuration options. 另一个建议:与其直接注入_connection字符串参数, CormarConfig创建一个CormarConfig类,该类.RegisterInstance注册以存储所有配置选项。 This way you just call RegisterType and let Autofac resolve all the type parameters (you get rid of those ugly Resolve calls). 这样,您只需调用RegisterType并让Autofac解析所有类型参数(即可摆脱那些难看的Resolve调用)。

If all your services inherit from a common ancestor or implement a common interface, you can register them all via Assembly Scanning and AsImplementedInterfaces . 如果您的所有服务都继承自一个共同的祖先或实现一个共同的接口,则可以通过Assembly ScanningAsImplementedInterfaces全部注册。 You would get rid of all the clutter in your module. 您将摆脱模块中的所有混乱情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM