views:

40

answers:

3

I'm creating an application that creates a Catalog of files. The data of the catalog will be stored in a database through NHibernate, but the actual files are just stored on a file system. I've abstracted the interface to the file system into an interface called IFileSystemAdaptor.

When an object is persisted from the database I need to set its IFileSystemAdaptor FileSystemAdaptor property so that its methods and properties can access the file system.

For example a user may later call AddAttachment(string filename, Stream data) on the persisted object. This will cause it to write the stream to the specified file name through its IFileSystemAdaptor, and add the new file name to its AttachmenFileNames property which will later be saved to the database.

Where can I insert code to set the the FileSystemAdaptor property for objects that are persisted from the database? Should I add a layer of abstraction between the Session/SessionFactory that sets the FileSystemAdaptor property before returning objects? Or is there someway I can inject this functinality into the SessionFactory so it returns objects with the FileSystemAdaptor already set?

A: 

I would treat that as an infrastructure concern. Your business logic could interact with the IFileSystemAdaptor and you could use Inversion of Control to pass concrete instances of FileSystemAdaptor to your business logic (the mapping between interface and concrete instance would be defined in web.config or app.config). This would allow you to create unit tests that pass in a mock instance of FileSystemAdaptor so your business logic would not have a dependency on the file system.

I would suggest implementing that class in a layer / project dedicated to infrastructure concerns or possibly an "Application Services" layer intended for application logic that is not necessarily business logic.

Mayo
+1  A: 

You could write a IPostLoadEventListener to set up your property after getting the entity from the database. Or use a custom bytecode provider to inject your entity with the IFileSystemAdaptor implementation.

Mauricio Scheffer
Sounds like the IPostLoadEventListener would be the simplest, however I can't find any documentation on this Interface in the NHibernate Reference Documentation.
Eric Anastas
I got it. Here's a blog post I found: http://www.codinginstinct.com/2008/04/nhibernate-20-events-and-listeners.html
Eric Anastas
A: 

Another (potentially unpopular?) option might be to simply use service location for this. I've found this an acceptable way to provide limited services to entities without getting into the complexity of using a custom bytecode provider, etc.

DanP
That might get complicated as my program has the potential to have multiple catalogs open simultaneously meaning two persisted objects may need to access different IFileSyStemAdaptors.
Eric Anastas
Ah yes, well I figured there was a good reason you didn't go the easy (lazy?) route and just use service location for this..you'll likely want to go the bytecode provider route, as suggested by Mauricio below...
DanP