Gayan
Gayan

Reputation: 2871

Constructor injection with Parameter

hi i'm trying to register repository class which having IDbConnection as constructor parameter.

public class Repository<TEntity> : IRepositoryAsync<TEntity> where TEntity : class
{
    public Repository(IDbConnection connection)
    {
        Connection = connection;
    }

    public IDbConnection Connection { get; }
}

i registered something like this

var container = new Container();
container.Options.DefaultScopedLifestyle = new WcfOperationLifestyle();
container.Register(typeof(IRepositoryAsync<>), typeof(Repository<>));
container.Register(typeof(IDbConnection), typeof(Repository<User>));
    container.Register<IAuthService, AuthService>();
container.Verify();

what was the wrong on my code?

Updated im getting exception like below

The constructor of type Repository contains the parameter with name 'connection' and type IDbConnection that is not registered. Please ensure IDbConnection is registered, or change the constructor of Repository.

Update 2

[ArgumentException: The supplied type Repository does not implement IDbConnection.Parameter name: implementationType]
SimpleInjector.Requires.ThrowSuppliedTypeDoesNotInheritFromOrImplement(Type service, Type implementation, String paramName) +63
SimpleInjector.Requires.ServiceIsAssignableFromImplementation(Type service, Type implementation, String paramName) +47
SimpleInjector.Container.Register(Type serviceType, Type implementationType, Lifestyle lifestyle, String serviceTypeParamName, String implementationTypeParamName) +159
SimpleInjector.Container.Register(Type serviceType, Type implementationType) +52
TimeTrackerService.Service.DependencyConfig..cctor() in D:\TimeTracking\TimeTrackerService\libs\TimeTrackerService.Service\DependencyConfig.cs:47[TypeInitializationException: The type initializer for 'TimeTrackerService.Service.DependencyConfig' threw an exception.]
TimeTrackerService.Service.DependencyConfig.get_Container() in D:\TimeTracking\TimeTrackerService\libs\TimeTrackerService.Service\DependencyConfig.cs:40 TimeTrackerService.WcfServiceFactory.CreateServiceHost(Type serviceType, Uri[] baseAddresses) in D:\TimeTracking\TimeTrackerService\TimeTrackerService\WcfServiceFactory.cs:15 System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String constructorString, Uri[] baseAddresses) +524
System.ServiceModel.HostingManager.CreateService(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) +1420
System.ServiceModel.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity) +52
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) +641[ServiceActivationException: The service '/TrackerService.svc' cannot be activated due to an exception during compilation. The exception message is: The type initializer for 'TimeTrackerService.Service.DependencyConfig' threw an exception..]
System.Runtime.AsyncResult.End(IAsyncResult result) +489035
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +174
System.ServiceModel.Activation.ServiceHttpModule.EndProcessRequest(IAsyncResult ar) +350322
System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +9747521

Upvotes: 2

Views: 2392

Answers (2)

Grundy
Grundy

Reputation: 13380

Yet another way, to avoid adding own interface and implementation.
Using this override for Register method:
Container.Register<TService>(Func<TService> instanceCreator, Lifestyle lifestyle)

Something like this:

container.Register<IDbConnection>(() =>{ 
    var con = ConfigurationManager.ConnectionStrings["TrackerConnection"]; 
    if (con == null) 
        throw new Exception("Failed to find connection"); 

    var _provider = DbProviderFactories.GetFactory(con.ProviderName); 

    var connection = _provider.CreateConnection(); 
    if (connection == null) 
        throw new Exception($"Failed to create a connection using the connection string named '{con.ProviderName}' in app.config or web.config."); 

    connection.ConnectionString = con.ConnectionString; 
    return connection; 
});

Upvotes: 1

Gayan
Gayan

Reputation: 2871

Finally i came up with solution. instead of injecting IDbConnection i inject own interface with implementation. IDataFactory and DataFactory. this implementation returns IDbConnection

private readonly string _providerName;
private readonly DbProviderFactory _provider;
public string ConnectionString { get; set; }

public DataFactory()
{
    var con = ConfigurationManager.ConnectionStrings["TrackerConnection"];
    if (con == null)
        throw new Exception("Failed to find connection");
    ConnectionString = con.ConnectionString;
    _providerName = con.ProviderName;
    _provider = DbProviderFactories.GetFactory(con.ProviderName);
}
public IDbConnection Connection
{
    get
    {
        var connection = _provider.CreateConnection();
        if (connection == null)
            throw new Exception($"Failed to create a connection using the connection string named '{_providerName}' in app.config or web.config.");
        connection.ConnectionString = ConnectionString;
        return connection;
    }
}

then i registered

container.Register<IDataFactory, DataFactory>();

Now i inject my implementation

public class Repository<TEntity> : IRepositoryAsync<TEntity> where TEntity : class
{
    public Repository(IDataFactory factory)
    {
        Factory= factory;
    }

    public IDataFactory Factory{ get; }
}

now when i use Factory.Connection it works as expected

thanks

Upvotes: 2

Related Questions