I\'m building an ASP.NET MVC application that uses a DDD (Domain Driven Design) approach with database access handled by NHibernate. I have domain model class (Administrator) th
There are already similar questions here on SO:
Dependency injection with NHibernate objects
DI/IoC, NHibernate and help in getting them to work together
You'll need to use Interceptors. Take a look at Fabio Maulo's post for implementation:
http://nhforge.org/blogs/nhibernate/archive/2008/12/12/entities-behavior-injection.aspx
Either hash the password in an application façade (if you are using any) or supply the IHashingService
implementation on every call to Administrator.SetPassword(..)
. I think it was called double dispatch?!
If you insist on DI-in-entity solution, I have done something like that with PostSharp AOP and PostSharp4Spring by declaring [Configurable]
attribute on the entity, but the solution is for Spring.Net. You can look here for more info. Also, if you are configuring NHibernate from the DI container, you can fall in a recursion trying to DI an entity before the container has finished configuring. You need a simple static class with method to suppress DI on entity construction during container initialization. Cannot provide an example a the moment though :(
You need to remember how it was hashed. This is so that you can hash a string in the future to check and see if it's their password, comparing that with the hashed value. That means that you need to store an enum or some other field in your object that indicates the hashing mechanism that was used in your database.
Otherwise, if you change your default hashing implementation, all of your old hashed passwords are no longer good, and your users will be left scratching their heads as to why their passwords no longer work--and you'll end up an IHashingService
interface that provides no flexibility (since the hashing implementation cannot be changed without adding weird rules like "use this hash for Administrators created before 2010-01-12"), existing for no real good reason.
To that end, I would add the appropriate field (an enum, a string returned by the IHashingService
interface, something) and either have NHibernate instantiate the hashing service for me via an IUserType
implementation, or I'd use a factory pattern where the concrete instances were provided to the factory by the IoC container. This would be combining Jarrett's method-level injection with a solution that allows re-hydrated objects to find their hashing implementations without being dependent on the IoC container.
Good luck!
Is there a reason that you can't pass the IHashingService
in the constructor for the Administrator
class? That's how I would resolve the dependency.
public class Administrator
{
private readonly IHashingService _hashingService;
public Administrator(IHashingService hashingService)
{
_hashingService = hashingService;
}
// <snip>
public void SetPassword(string plainTextPassword)
{
this.HashedPassword = _hashingService.Hash(plainTextPassword);
}
}
Edit #1
If pulling from a model, try using method-level injection.
public void SetPassword(string plainText, IHashingService hasher)
{
if (hasher == null) throw new ArgumentNullException("hasher");
this.HashedPassword = hasher.Hash(plainText);
}
Edit #2
Also, why not make it easy on yourself and just make an extension on string?
public static class ExtensionsOfString
{
public static string Hash(this string s)
{
// hash with SHA256
return hashedString;
}
}
While I do realize that there's a "replaceable" code aspect of using dependency injection, this isn't exactly a big deal for this example. You don't really need a IPasswordEncryptionService the same way you'd need a, say, ICreditCardAuthorizationService. If, someday, you change your hashing algorithm from SHA256 to SHA512, you will now have invalidated every password in your database.