使用 Autofac 注入工厂与委托工厂
Injecting factory using Autofac vs. delegate factories
我是 Autofac 的新用户。
我有一个工厂需要根据工厂方法的输入创建一个不同的 class,但只有一个需要创建的 class 有其他依赖项。
我找到了这个答案:
Autofac Binding at Runtime
谁的解决方案效果很好。
但后来我开始阅读 Autofac 的委托工厂 (http://docs.autofac.org/en/latest/advanced/delegate-factories.html)...现在我很困惑。
看起来,如果您使用委托工厂,那么您实际上根本不需要编写工厂class?
这是我当前工厂的截图 class:
public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
{
private readonly IComponentContext autofacContainer;
public ExternalUserInformationProviderFactory(IComponentContext autofacContainer)
{
this.autofacContainer = autofacContainer;
}
public IProvideExternalUserInformation GetExternalUserInformationProvider(string loginProvider)
{
switch (loginProvider)
{
case "Google":
return autofacContainer.Resolve<GoogleExternalUserInformationProvider>();
case "Twitter":
return autofacContainer.Resolve<TwitterExternalUserInformationProvider>();
}
return null;
}
}
在此示例中,TwitterExternalUserInformationProvider 在其构造函数中采用依赖项:
public class TwitterExternalUserInformationProvider : IProvideExternalUserInformation
{
private readonly ITwitterRepository twitterRepository;
public TwitterExternalUserInformationProvider(ITwitterRepository twitterRepository)
{
this.twitterRepository = twitterRepository;
}
}
并且 GoogleExternalUserInformationProvider 根本不接受构造函数参数。
这是我在 Startup.cs 中连接工厂的方式(我使用的是 asp.net 内核):
var containerBuilder = new ContainerBuilder();
containerBuilder.Register<IExternalUserInformationProviderFactory>(c => new ExternalUserInformationProviderFactory(c.Resolve<IComponentContext>()));
containerBuilder.RegisterType<TwitterExternalUserInformationProvider>();
containerBuilder.RegisterType<GoogleExternalUserInformationProvider>();
Autofac 足够聪明,可以为我解决 ITwitterRepository 依赖,这真的很酷。
基于当前的实现,我是否可以使用委托工厂并完全摆脱 ExternalUserInformationProviderFactory?
很好奇
谢谢
委托工厂不会在服务的两种实现之间进行选择,它只会根据其依赖项创建一个组件。
在你的情况下你需要一个工厂。您的工厂可能还依赖于 IIndex<String, IProvideExternalUserInformation>
而不是依赖于 IComponentContext
,这可以避免 scope & co.
的问题
您的 ExternalUserInformationProviderFactory
可能如下所示:
public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
{
public ExternalUserInformationProviderFactory(IIndex<String, IProvideExternalUserInformation> providers)
{
this._providers = providers;
}
private readonly IIndex<String, IProvideExternalUserInformation> _providers;
public IProvideExternalUserInformation GetExternalUserInformationProvider(String loginProvider)
{
IProvideExternalUserInformation provider;
if (!this._providers.TryGetValue(loginProvider, out provider))
{
throw new Exception("boom");
}
return provider;
}
}
以及您的注册:
builder.RegisterType<TwitterExternalUserInformationProvider>()
.Named<IProvideExternalUserInformation>("twitter");
builder.RegisterType<GoogleExternalUserInformationProvider>()
.Named<IProvideExternalUserInformation>("google");
builder.RegisterType<ExternalUserInformationProviderFactory>()
.As<IExternalUserInformationProviderFactory>();
我是 Autofac 的新用户。
我有一个工厂需要根据工厂方法的输入创建一个不同的 class,但只有一个需要创建的 class 有其他依赖项。
我找到了这个答案: Autofac Binding at Runtime
谁的解决方案效果很好。
但后来我开始阅读 Autofac 的委托工厂 (http://docs.autofac.org/en/latest/advanced/delegate-factories.html)...现在我很困惑。
看起来,如果您使用委托工厂,那么您实际上根本不需要编写工厂class?
这是我当前工厂的截图 class:
public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
{
private readonly IComponentContext autofacContainer;
public ExternalUserInformationProviderFactory(IComponentContext autofacContainer)
{
this.autofacContainer = autofacContainer;
}
public IProvideExternalUserInformation GetExternalUserInformationProvider(string loginProvider)
{
switch (loginProvider)
{
case "Google":
return autofacContainer.Resolve<GoogleExternalUserInformationProvider>();
case "Twitter":
return autofacContainer.Resolve<TwitterExternalUserInformationProvider>();
}
return null;
}
}
在此示例中,TwitterExternalUserInformationProvider 在其构造函数中采用依赖项:
public class TwitterExternalUserInformationProvider : IProvideExternalUserInformation
{
private readonly ITwitterRepository twitterRepository;
public TwitterExternalUserInformationProvider(ITwitterRepository twitterRepository)
{
this.twitterRepository = twitterRepository;
}
}
并且 GoogleExternalUserInformationProvider 根本不接受构造函数参数。
这是我在 Startup.cs 中连接工厂的方式(我使用的是 asp.net 内核):
var containerBuilder = new ContainerBuilder();
containerBuilder.Register<IExternalUserInformationProviderFactory>(c => new ExternalUserInformationProviderFactory(c.Resolve<IComponentContext>()));
containerBuilder.RegisterType<TwitterExternalUserInformationProvider>();
containerBuilder.RegisterType<GoogleExternalUserInformationProvider>();
Autofac 足够聪明,可以为我解决 ITwitterRepository 依赖,这真的很酷。
基于当前的实现,我是否可以使用委托工厂并完全摆脱 ExternalUserInformationProviderFactory?
很好奇
谢谢
委托工厂不会在服务的两种实现之间进行选择,它只会根据其依赖项创建一个组件。
在你的情况下你需要一个工厂。您的工厂可能还依赖于 IIndex<String, IProvideExternalUserInformation>
而不是依赖于 IComponentContext
,这可以避免 scope & co.
您的 ExternalUserInformationProviderFactory
可能如下所示:
public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
{
public ExternalUserInformationProviderFactory(IIndex<String, IProvideExternalUserInformation> providers)
{
this._providers = providers;
}
private readonly IIndex<String, IProvideExternalUserInformation> _providers;
public IProvideExternalUserInformation GetExternalUserInformationProvider(String loginProvider)
{
IProvideExternalUserInformation provider;
if (!this._providers.TryGetValue(loginProvider, out provider))
{
throw new Exception("boom");
}
return provider;
}
}
以及您的注册:
builder.RegisterType<TwitterExternalUserInformationProvider>()
.Named<IProvideExternalUserInformation>("twitter");
builder.RegisterType<GoogleExternalUserInformationProvider>()
.Named<IProvideExternalUserInformation>("google");
builder.RegisterType<ExternalUserInformationProviderFactory>()
.As<IExternalUserInformationProviderFactory>();