Autofac - None of the constructors found with 'Public binding flags' - nhibernate

I keep on getting an error when trying to resolve my repositories.
None of the constructors found with 'Public binding flags' on type can be invoked with the available services and parameters:
Cannot resolve parameter 'Repository.Data.INHibernateSession nHibernateSession' of constructor 'Void .ctor(Repository.Data.INHibernateSession)'.
Global.asax
builder.RegisterAssemblyTypes(assembly).Where(t => typeof(IDependency).IsAssignableFrom(t)).
AsImplementedInterfaces().InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(assembly).Where(t => typeof(ISingletonDependency).IsAssignableFrom(t)).
AsImplementedInterfaces().SingleInstance();
builder.RegisterAssemblyTypes(assembly).Where(t => typeof(ITransientDependency).IsAssignableFrom(t)).
AsImplementedInterfaces().InstancePerDependency();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency();
then i have my singleton factory
public interface INhibernateFactory : ISingletonDependency
{
ISessionFactory SessionFactory { get; }
}
then my instance per lifetime
public interface INHibernateSession : IDependency
{
ISession Session { get; }
}
public class NHibernateSession : IDependency
{
private ISession _session;
private readonly ISessionFactory _sessionFactory;
public NHibernateSession(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
then in my Generic repository
public class Repository<T> : IRepository<T> where T : class
{
private readonly INHibernateSession _nHibernateSession;
public Repository(INHibernateSession nHibernateSession)
{
_nHibernateSession = nHibernateSession;
}
public ISession Session
{
get { return _nHibernateSession.Session; }
}
It seems all i'm doing is creating a singleton, inject that to the session, then inject into repository. (all my other dependencies work fine)
Appreciate if someone could point me in the right direction why this wont resolve, I'm quite stumped?

The errors you get speaks for them selves, they state some type that cannot be resolved. After your latest change, this is the the 'ISessionFactory' interface which is missing.
To further elaborate: the current problem is that Autofac, when asked to build NHibernateSession instances, doesn't know how to provide an ISessionFactory instance. To "learn" the container how to build session factories it is not enough to provide the NHibernateFactory instance alone. Consider this registration:
builder.RegisterType<NhibernateFactory>().As<INhibernateFactory>().SingleInstance();
builder.Register(c => c.Resolve<INhibernateFactory>().SessionFactory);
The last line there registers a lambda that knows how to provide the session factory instance.
You'll need to provide the container with every type involved. Use the "no constructors..." error to see which types are missing.
To dig further into Autofac and NHibernate you'll have to search around the net. E.g. this question discusses NHibernate sessions:
Managing NHibernate ISession with Autofac

I am not familiar with AutoFac; but does your NHibernateSession class have to implement your INHibernateSession interface to resolve correctly?
Matt

Related

How to inject or wire up ormlite into ServiceStack repositories?

I want to access the database from a repository rather than the service class (for increased seperation - not sure if this is overkill tho) i.e.
public class TodoRepository // : BaseRepository derive the class and inject IDbConnection somehow?
{
public List<Todo> GetByIds(long[] ids)
{
return Db.Select<Todos>(t => Sql.In(t.id, ids)); <-- how to get 'Db' in here
}
}
The service base class already enables direct access to databases via ormlite using 'Db' object thus:
public class Service : IService, IRequiresRequestContext, IServiceBase, IResolver, IDisposable
{
public virtual IDbConnection Db { get; }
}
Leading me to believe I can do this perhaps so I can use 'Db' in derived classes:
public class BaseRepository: IDisposable
{
public virtual IDbConnection Db { get; }
}
My AppHost has this line in it to pass in the connection string and register the repository:
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));
container.Register(new TodoRepository());
How to inject or autowire up the IDbConnection to the BaseRepository class? I've already attempted registering and autowiring the BaseRepository in the AppHost with no luck.
Please see the Autowire registration section in the IOC wiki docs.
This just registers a singleton instance, since you're passing in an existing instance the IOC is not able to control the creation of the type:
container.Register(new TodoRepository());
If you want it auto-wired, you need to use one of the auto-wired APIs:
container.RegisterAutoWired<TodoRepository>();
container.RegisterAutoWiredAs<TodoRepository,ITodoRepository>();
container.RegisterAs<TodoRepository,ITodoRepository>(); //shorter alias
container.RegisterAutoWiredType(typeof(MyType));
container.RegisterAutoWiredType(typeof(MyType),typeof(IMyType));
container.RegisterAutoWiredTypes(typeof(MyType),typeof(MyType2),typeof(MyType3));
Or you can manually control the creation of your instance by specifying a factory method:
container.Register(c => new TodoRepository {
DbFactory = c.Resolve<IDbConnectionFactory>()
});
If you want to inject an IDbConnection instead make sure it's in Request or None Scope:
container.Register<IDbConnection>(c =>
c.Resolve<IDbConnectionFactory>().OpenDbConnection()
)
.ReusedWithin(ReuseScope.Request);

bind to property always return null

I am trying to bind a repository to property using Ninject but always get null reference of binding object. I will explain the problem using code below.
public interface IServiceRepository
{
User GetUser(string email);
IQueryable<Statistic> GetStatisticForCurrentMonth(string ip);
void InsertStatistic(ConversionModel conversionModel);
class ServiceRepository : IServiceRepository
{
//Implementation of the Interface
}
I am would like to bind the repository above to class below while the class is created. Unfortunately Repository object is always null. Maybe I have misunderstood how Ninject is working? How to solve the problem?
public class Converter
{
[Inject]
public static IServiceRepository Repository { get; set; }
private static Converter _converter;
public static Converter Instance
{
get { return _Converter ?? (_Converter = new Converter ());
}
}
Ninject activator code
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().ToMethod(context => Converter.Repository);
}
Update
I have tried to rewrite code like this
public class Converter
{
private readonly IServiceRepository _repository;
public Converter(IServiceRepository repository)
{
_repository = repository;
}
//skip code
}
The test...
[TestMethod]
public void ConverterInstanceCreated()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
Assert.IsNotNull(kernel.Get<Converter>());
}
}
gives exception
Test method PC.Tests.NinjectTest.ConverterInstanceCreated threw exception:
Ninject.ActivationException: Error activating IServiceRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IServiceRepository into parameter repository of constructor of type Converter
1) Request for Converter
I just lost, I am trying to understand how Ninject is working for about week without any success. In my case why this exception is thrown?
Also please someone post working example with one repository injection to singleton class.
Ninject does not inject statics. Change the coynverter to a non-static class and configure it as Singleton in ninject. Also use constructor injection and make the repo a private field.
Now you can inject the converter to the constructors where you need it.
Even though you are using Property injection and not Constructor injection I think it would still be
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
}
As ninject still just needs to know what concrete type to map to the Interface
I haven't tested this so apologies if it's wrong.

Ninject property binding, how to do correctly

I have installed Ninject (v4.0.30319) package in test project to test. Create test code below, unfortunately ValidateAbuse.Instance.Repository is always Null. Why Ninject do not bind repository to ValidateAbuse.Repository property?
Some of you may suggest to use constructor binding but I can't use it due to code structure. The below code is just example and I need to find a way to bind to property.
Test method which always fail
[TestMethod]
public void PropertyInjection()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<ISettingsRepository>().To<SettingsRepository>();
Assert.IsNotNull(ValidateAbuse.Instance.Repository);
}
}
The repository interface
public interface ISettingsRepository
{
List<string> GetIpAbuseList();
List<string> GetSourceAbuseList();
}
The repository implementation
public class SettingsRepository : ISettingsRepository
{
public List<string> GetIpAbuseList()
{
return DataAccess.Instance.Abuses.Where(p => p.TypeId == 1).Select(p => p.Source).ToList();
}
public List<string> GetSourceAbuseList()
{
return DataAccess.Instance.Abuses.Where(p => p.TypeId == 2).Select(p => p.Source).ToList();
}
}
The class to which I am trying to bind repository
public class ValidateAbuse
{
[Inject]
public ISettingsRepository Repository { get; set; }
public static ValidateAbuse Instance = new ValidateAbuse();
}
Ninject will only bind properties on an object when it creates an instance of that object. Since you are creating the instance of ValidateAbuse rather than Ninject creating it, it won't know anything about it and therefore be unable to set the property values upon creation.
EDIT:
You should remove the static singleton from ValidateAbuse and allow Ninject to manage it as a singleton.
kernel.Bind<ValidateAbuse>().ToSelf().InSingletonScope();
Then when you ask Ninject to create any class that needs an instance of ValidateAbuse, it will always get the same instance.
It seems like you don't fully understand how Ninject works or how to implement it so I would suggest you read the wiki https://github.com/ninject/ninject/wiki/How-Injection-Works and follow some more basic examples before trying to wire it into an existing application.

Does StructureMap have scoping corresponding to NInject's DefinesNamedScope/InNamedScope?

The problem I'd like to solve is sharing an ISessionProvider between IXyzRepositories (where ISessionProvider holds the current NHibernate ISession).
I'm tweaking the "Setting up session per presenter" recipe from NHibernate 3 Cookbook, and would like to keep StructureMap (brownfield project).
I think you would have to create a custom Lifecyle to do that, although I am not sure what exactly you are trying to accomplish...
To create a custom Lifecycle, you just have to implement the ILifecycle interface and the use it in your registration. Here is an example you can look at: http://blog.mikeobrien.net/2010/01/creating-structuremap-lifecycle-for-wcf.html.
In a web application I use Singleton for the sessionFactory and HybridHttpOrThreadLocalScoped for the session:
This is my structuremap registry:
public class NhibernateRegistry: Registry
{
public NhibernateRegistry()
{
For<ISessionFactory>()
.Singleton()
.Use(new NHibernateSessionFactory(connectionString).SessionFactory);
For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(o => o.GetInstance<ISessionFactory>().CurrentSession);
}
}
My NHibernateSessionFactory is similar to SessionProvider class used in the book.
Everything is disposed at the end of the request (web app):
protected void Application_EndRequest(object sender, EventArgs e)
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
I use a generic repository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly ISession _session;
public GenericRepository(ISession session)
{
_session = session;
}
public T Load(Guid Code)
{
return (_session.Load<T>(Code));
}
}
but you can easily change it with your own implementation.
I register the repository here:
public class RepositoriesRegistry : Registry
{
public RepositoriesRegistry()
{
For <Data.IRepository<Domain.Reminder, Guid>>()
.HybridHttpOrThreadLocalScoped()
.Use<Data.NH.Repository<Domain.Reminder, Guid>>();
}
}

Entity framework DbContext in wcf per call instance mode

I have a repository like this
public abstract class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DbContext _dbContext;
public BaseRepository(DbContext dbContext)
{
_dbContext = dbContext;
}
public TEntity GetByKey(object keyValue)
{
// todo
}
}
and a concrete repository like this
public CustomerRepository : BaseRepository<Customer> , ICustomerRepository
{
public CustomerRepository(DbContext context) : base (context) { }
public Customer FindCustomerByKey(string key)
{
_dbContext.Set<Customer>().Find(key);
}
}
I have wcf service like this
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CustomerSatisfactionService : ICustomerSatisfactionService
{
private ICustomerRepository _customerRepository;
private IHelpDeskRepository _helpdeskRepository;
public AccountService(ICustomerRepository customerRepository,IHelpdeskRepository helpdeskRepository)
{
_customerRepository = customerRepository;
_helpdeskRepository = helpdeskRepository;
}
public void DoSomethingUsingBothRepositories()
{
// start unit of work
// _customerRepository.DoSomething();
// _helpdeskRepository.DoSomething();
// commit unit of work
}
}
and I am using StructureMap for injecting DbContext instances like this
For<DbContext>().Use(() => new MyApplicationContext());
My problem is when a client calls the service, a new CustomerSatisfactionService instance is created, hence new instances of CustomerRepository and HelpdeskRepository are created but with different DbContexts.
I want to implement the unit of work pattern, but in the DoSomethingWithBothRepositories method, the two repositories have different DbContexts.
Is there any way to tell structure map to spin up a DbContext instance on a per call basis?
You must specify lifecycle for your DbContext so that only one instance is created per call. StructureMap doesn't contain build-in lifecycle management for per call WCF but you can find one implementation on this blog.
You need to implement UnitOfWork pattern so that same context is shared amongst entities. Take a look at http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx for a way to implement it.
I don't know if you need/want StructureMap to control the instantiation of dbcontext, have a look at this reply, UoW and UoW Factory setup dbcontext for the calls that need to be made in the repository.
EF ObjectContext, Service and Repository - Managing context lifetime.