Constructor dependency injection with NHibernate 2.1 and StructureMap - nhibernate

I've read somewhere that NHibernate 2.1 supports constructor dependency injection for it's entites.
How do I go about configuring StructureMap and NHibnerate 2.1 to get this up and running ?

I realize this is an old question, but in case it might be useful.
EDIT: Original posted links weren't effective for NHib 2.1, found better info.
For NHibernate 2.1, you can create an Interceptor and override the Instantiate method and have your container create your instances there. Here is an example
If you wanted to do property injection instead, you can use the same technique but do your work in the onLoad method instead.

By setting up StructureMap across all of your entities (classes etc) and then using the interface for each of those as the signature for the constructor of a class...when you instantiate the class that has a dependency in its constructor StructureMap will auto inject it for you!
[PluginFamily("Default")]
public interface IWidget1
[Pluggable("Default")]
public class Widget1 : IWidget1
[PluginFamily("Default")]
public interface IAnotherWidget
[Pluggable("Default")]
public class AnotherWidget : IAnotherWidget
{
public AnotherWidget(IWidget widget)
{
...
}
}
IAnotherWidget _anotherWidget = ObjectFactory.GetInstance<IAnotherWidget>();
Something like that!
This may be of use too: Can I replace the call to Activator.CreateInstance() in NHibernate?
And this: http://devlicio.us/blogs/billy_mccafferty/archive/2007/02/05/inject-di-container-into-domain-objects-with-nhibernate.aspx

Related

ASP.Net Core Open Partial Generic Dependency Injection

I would like to register the following items for DI using an open generic implementation and interface. I know the following example will not work, as well as other combinations I've tried with MakeGenericType, or GetGenericArguments. I would like to simply call AddRepository<MyDbContext> and then be able to inject my implementation into classes without explicitly having to register the type I am using.
Interface
public interface IRepository<TEntity>
{
}
Implementation
public class Repository<TEntity, TContext> : IRepository<TEntity>
where TEntity : class
where TContext : DbContext
{
}
Registration
public static class RepositoryServiceCollectionExtensions
{
public static IServiceCollection AddRepository<TContext>(
this IServiceCollection services) where TContext : DbContext
{
services.TryAddScoped(
typeof(IRepository<>),
typeof(Repository< , TContext>));
return services;
}
}
The dependency injection container Microsoft.Extensions.DependencyInjection and its abstraction layer does not support open generic factories. So you generally cannot achieve what you would like to do there. There’s also no support planned.
Unlike many those other dependency injection related features, this is also not really possible to patch by just providing the right wrapper or factory types. So you will actually have to change your design here.
Since you want to resolve IRepository<TEntity> and the only way to do this is by registering an equivalent open generic type, you will have to have some type Repository<TEntity> that implements your repository. That makes it impossible to retrieve the database context type from the generic type argument, so you will have to use a different way here.
You have different options to do that. For example, you could configure your Repository<TEntity> (e.g. using M.E.Options) with the context type and make that resolve the Repository<TEntity, TContext> dynamically. But since you have actual control over your database context, I would suggest either adding a marker interface or introducing another type for the context which you can then register with the container:
public class Repository<TEntity> : IRepository<TEntity>
{
public Repository(IDbContext dbContextFactory)
{ … }
}
public class MyDbContext : DbContext, IDbContext
{ … }
Then, your extension method could look like this:
public static IServiceCollection AddRepository<TContext>(this IServiceCollection services)
where TContext : DbContext, IDbContext
{
services.AddTransient(typeof(IDbContext), sp => sp.GetService<TContext>());
services.TryAddScoped(typeof(IRepository<>), typeof(Repository<>));
return services;
}
Of course, this changes how your Repository implementation works, but I don’t actually assume that you need to know the TContext type other than to inject the database context type. So this will probably still work for you.
That being said, I have too agree with Chris Pratt, that you probably don’t need this. You say that you want to introduce the repository, because “coding stores and implementations for every entity is a time consuming task” but you should really think about whether you actually need that. A generic repository is very limited in what it can do, and mostly means that you are doing just CRUD operations. But exactly that is what DbContext and DbSet<T> already do:
C: DbContext.Add, DbSet<T>.Add
R: DbContext.Find, DbSet<T>.Find
U: DbContext.Update, DbSet<T>.Update
D: DbContext.Remove, DbSet<T>.Remove
In addition, DbContext is a “unit of work” and DbSet<T> is an IQueryable<T> which gives you a lot more control and power than a generic repository could possible give you.
You cannot have a partially open generic reference. It's all or nothing. In other words, you can try:
services.TryAddScoped(
typeof(IRepository<>),
typeof(Repository<,>));
But, if that doesn't work, you'll likely need to add a type param to your AddRepository method:
public static IServiceCollection AddRepository<TEntity, TContext>(this IServiceCollection services)
where TEntity : class
where TContext : DbContext
{
services.TryAddScoped(
typeof(IRepository<TEntity>),
typeof(Repository<TEntity, TContext>));
return services;
}
Of course, I think that breaks what you're ultimately trying to achieve here: registering repositories for all the entity types in one go. You can always use a bit of reflection find all entities in your assembly (they would need to share something in common: base class, interface, etc.) and then enumerate over them and use reflection to call AddScoped on your service collection for each.
All that said, the best thing you can do here is to actually throw all this away. You don't need the repositories. EF already implements the repository and unit of work patterns. When you use an ORM like EF, you're essentially making that your data layer instead of a custom class library you create. Putting you own custom wrapper around EF not only adds entropy to your code (more to maintain, more to test, and more than can break), but it can also mess up the way EF works in many cases, leading to less efficiency in the best cases and outright introducing bugs into your application in the worst cases.

NHibernate and IoC IInterceptor

I have been trying to implement a solution similar to what Ayende posts in his MSDN article, Building a Desktop To-Do Application with NHibernate. Fortunately, Skooletz wrote a similar article that follows up what I am trying to accomplish with his 3 part blog post on NHibernate interceptor magic tricks (1, 2, 3). I am having trouble getting my POCO object's parametered constructor to be called by NHibernate when instantiating the object.
When I remove the protected parameterless constructor, NHibernate complains with an InvalidProxyTypeException: "The following types may not be used as proxies:
YourNamespace.YourClass: type should have a visible (public or protected) no-argument constructor". If I then add in the protected default constructor, NHibernate no longer complains, but the dependency (in the overloaded constructor) is never called causing the application to barf with a NullReferenceException at runtime when the dependency is not satisfied.
public MyClass
{
IRequiredDependency dependency;
public MyClass(IRequiredDependency dependency)
{
this.dependency = dependency;
}
protected MyClass() {}
}
I just can't seem to get NHibernate to call the overloaded constructor. Any thoughts?
In the configuration of the IoC container, you have to declare your type with the dependency in addition to the dependency itself.
container.RegisterType<IRequiredDependency, RequiredDependency>();
container.RegisterType<MyClass, MyClass>();
I missed that little tidbit from Pablo's post (where he registers the Invoice class in addition to its dependency, IInvoiceTotalCalculator) as I am using Unity instead of Windsor.
One additional note: I found is that if you would like to have any other overloaded constructors, make them internal, leave the default constructor as protected and have only a single public constructor that contains your dependencies. This tidbit helped tighten up some of my API design for the classes.

Executing order of constructor injection and property injection using ninject 2

I'm loading a ninject module in my (WCF) project and want to hook up log4net in my module using a custom provider. The reason I'm using a provider is that the GetLogger method needs to get passed the class in which the Injection is taking place. If this is not the way to do this, please let me know, I'm new to Ninject. (Context.getType() is not correct btw, I'm having some trouble doing this.)
The main problem is that my ILog variables in my classes get Initialized after the constructor has executed, but I want to be able to use the logging in my constructor. I am also using Ninject to call my constructor and bind it's parameters to concrete classes.
Bind<IBroker>().To<Broker>(); // constructor
Bind<ILog>().ToProvider(new log4netILogProvider()) // property
private class log4netILogProvider : Ninject.Activation.Provider<ILog>
{
protected override ILog CreateInstance(IContext context)
{
return LogManager.GetLogger(context.getType());
}
}
All help is appreciated.
No IoC framework will ever be able to do property injection before constructor injection. An IoC framework can only do the same things you can do in a manually written factory. You can't access a property of an object in a factory before it has been created right? So can't the IoC framework.
Basically you have two options.
Do constructor injection (prefered)
Do method injection and execute your constructor code in the method.
[Inject]
public void Initialize(ILog log) { ... }
I would also suggest a third option. You can implement Ninject's IInitializable interface then see if you can't move the code that relies on the property injecttor into your implementation of Initialize(). Ninject guarantess that all constructor injection AND propery injection is finished before Initialize is invoked.

Looking for Ninject equivalent of StructureMap's ObjectFactory.GetInstance() method

I'm using Ninject in an MVC project and I've used the autoregistration features in Ninject.Mvc and have my bindings set up in my application class. However, I have a place where I want to create an instance separate from those bindings. In StructureMap, you can do var foo = ObjectFactory.GetInstance<IFoo>(); and it will resolve it for you. Is there an equivalent in Ninject 2? I can't seem to find it anywhere.
AFAIK, NInject doesn't have static method like this so all resolving should go to some kernel.
But you can implement it easily;
class ObjectFactory
{
static IKernel kernel = new StandardKernel(.....);
public static T GetInstance<T>()
{
return kernel.Get<T>();
}
}
Although, IMO, NInject is much more useful as DI container than as service locator.
You can also use Common Service Locator as an abstraction layer for Ninject IOC which offers what you want. The advantage is that you can later switch container if it does not fit your needs anymore.
In your code you can use something like this:
ServiceLocator.Current.GetInstance<Type>();

Applying Spring .Net Advice to HibernateTemplate object

I have an class for auditing:
public class AuditAfterAdvise : IAfterReturningAdvice
This is applied to a Dao class in my Spring.Net configuration, using a RegularExpressionMethodPointcutAdvisor.
The Dao class implementation calls HibernateTemplate.SaveOrUpdate(object entity) to commit changes.
I would like to be able to apply AuditAfterAdvise class to the HibernateTemplate SaveOrUpdate() method used in my Dao, rather than the methods on the Dao itself.
The NHibenate/Spring setup is to use a LocalSessionFactoryObject for the Dao. Is this possible?
Thanks.
It certainly should be possible.
Instead of configuring the Dao, add the advice to the object definition for the LocalSessionFactoryObject. The RegularExpressionPointCutAdvisor should continue to work -- just applied to a different object.
I'm assuming the HibernateTemplate is retrieved from a Spring.NET object factory...