I am trying to create with Autofac a 'generated' factory that will resolve dependencies in real-time based on an enum parameter.
Given the following interfaces/classes:
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(); } }
I'd like to use Autofac to generate some sort of factory that has a method that receives one parameter: ConnectionType and returns the correct connection object.
I started with the following registrations:
builder.RegisterType<AutoFacConcepts.Engine.Engine>() .As<IEngine>() .InstancePerDependency(); builder.RegisterType<SshConnection>() .As<IConnection>(); builder.RegisterType<TelnetConnection>() .As<IConnection>();
I then continued to play with the TelnetConnection/SshConnection registrations with different options:
I couldn't find the correct combination of the registrations that will allow me to define a generated factory delegate that will return the correct connection object (SshConnection for ConnectionType.Ssh and TelnetConnection for ConnectionType.Telnet).
Update the Engine
class to take a Func<ConnectionType, IConnection>
instead of the delegate. Autofac supports creating delegate factories on the fly via 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(); } }
In your registration use a lambda that grabs up the parameter and returns the correct IConnection
instance.
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>();
If the connection itself required a dependency you could call Resolve
on the c
parameter to resolve it from the current call context. For example, new SshConnection(c.Resolve<IDependency>())
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With