autoface -如何创建带有参数的生成工厂
本文关键字:参数 工厂 何创建 创建 autoface | 更新日期: 2023-09-27 18:18:56
我正在尝试使用Autofac创建一个'生成'工厂,该工厂将基于enum参数实时解析依赖项。
给定以下接口/类:
public delegate IConnection ConnectionFactory(ConnectionType connectionType);
public enum ConnectionType
{
Telnet,
Ssh
}
public interface IConnection
{
bool Open();
}
public class SshConnection : ConnectionBase, IConnection
{
public bool Open()
{
return false;
}
}
public class TelnetConnection : ConnectionBase, IConnection
{
public bool Open()
{
return true;
}
}
public interface IEngine
{
string Process(ConnectionType connectionType);
}
public class Engine : IEngine
{
private ConnectionFactory _connectionFactory;
public Engine(ConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
public string Process(ConnectionType connectionType)
{
var connection = _connectionFactory(connectionType);
return connection.Open().ToString();
}
}
我想使用autofacc生成某种类型的工厂,它有一个方法,接收一个参数:ConnectionType并返回正确的连接对象。
我从以下注册开始:
builder.RegisterType<AutoFacConcepts.Engine.Engine>()
.As<IEngine>()
.InstancePerDependency();
builder.RegisterType<SshConnection>()
.As<IConnection>();
builder.RegisterType<TelnetConnection>()
.As<IConnection>();
然后我用不同的选项继续使用TelnetConnection/SshConnection注册:
- 名为<
- /gh>
- 的 <
- 元数据/gh>
我找不到注册的正确组合,这将允许我定义一个生成的工厂委托,它将返回正确的连接对象(SshConnection for ConnectionType)。
更新Engine
类,使其接受Func<ConnectionType, IConnection>
而不是委托。Autofac支持通过Func<T>
动态创建委托工厂。
public class Engine : IEngine
{
private Func<ConnectionType, IConnection> _connectionFactory;
public Engine(Func<ConnectionType, IConnection> connectionFactory)
{
_connectionFactory = connectionFactory;
}
public string Process(ConnectionType connectionType)
{
var connection = _connectionFactory(connectionType);
return connection.Open().ToString();
}
}
在您的注册中使用一个lambda来获取参数并返回正确的IConnection
实例。
builder.Register<IConnection>((c, p) =>
{
var type = p.TypedAs<ConnectionType>();
switch (type)
{
case ConnectionType.Ssh:
return new SshConnection();
case ConnectionType.Telnet:
return new TelnetConnection();
default:
throw new ArgumentException("Invalid connection type");
}
})
.As<IConnection>();
如果连接本身需要一个依赖,你可以在c
参数上调用Resolve
来从当前调用上下文中解决它。例如:new SshConnection(c.Resolve<IDependency>())
.
如果需要根据参数选择实现类型,则需要使用IIndex<T,B>
隐式关系类型:
public class Engine : IEngine
{
private IIndex<ConnectionType, IConnection> _connectionFactory;
public Engine(IIndex<ConnectionType, IConnection> connectionFactory)
{
_connectionFactory = connectionFactory;
}
public string Process(ConnectionType connectionType)
{
var connection = _connectionFactory[connectionType];
return connection.Open().ToString();
}
}
用枚举键注册你的IConnection
实现:
builder.RegisterType<Engine>()
. As<IEngine>()
.InstancePerDependency();
builder.RegisterType<SshConnection>()
.Keyed<IConnection>(ConnectionType.Ssh);
builder.RegisterType<TelnetConnection>()
.Keyed<IConnection>(ConnectionType.Telnet);
如果你想保留你的ConnectionFactory
,你可以手动注册它使用IIndex<T,B>
内部:
builder.Register<ConnectionFactory>(c =>
{
var context = c.Resolve<IComponentContext>();
return t => context.Resolve<IIndex<ConnectionType, IConnection>>()[t];
});
在这种情况下,你仍然需要注册你的IConnection
类型为关键,但你的Engine
实现可以保持不变。