I'm trying to implement the Strategy Pattern with Fluent Nhibernate, inspired by this blog post
public abstract class Strategy
{
protected Strategy() { }
protected Strategy(Guid id) { this.Id = id; }
public virtual Guid Id { get; set; }
public abstract void SomeMethod();
}
public class MyStrategy : Strategy
{
public MyStrategy() : base(new Guid("F1CF041B ...")) { }
public override void SomeMethod() { }
}
public class StrategyMap : ClassMap<Strategy>
{
public StrategyMap()
{
this.Id(x => x.Id).GeneratedBy.Assigned();
this.DiscriminateSubClassesOnColumn("Id");
}
}
public class MyStrategyMap : SubclassMap<MyStrategy>
{
public MyStrategyMap()
{
this.DiscriminatorValue("F1CF041B ...");
}
}
But when I run the following test (where this.Session
is from a in-memory-database):
[TestMethod]
public void CanGetMyStrategy()
{
// Arrange
using (var transaction = this.Session.BeginTransaction())
{
this.Session.Save(new MyStrategy());
transaction.Commit();
this.Session.Clear();
}
// Act
var strategies = this.Session.Query<Strategy>();
// Assert
Assert.IsNotNull(strategies.FirstOrDefault());
}
The following exception is thrown:
NHibernate.WrongClassException:
Object with id: f1cf041b ...
was not of the specified subclass: Namespace.Strategy
(Discriminator was: 'f1cf041b ...')
Any help debugging this issue would be appreciated as I can't figure out why this doesn't work.
Unsatifactory solution
I can get the code to work by not discriminating on the Id column (and so creating another column to discriminate on), but I find this unsatisfactory as it means duplicating data.
Why Guid?
The reasoning behind this is that new Strategy
s will be able to be created via a plugin architecture (providing an implementation of Strategy
and SubclassMap<[strategy-name]>
which get read at application load), and as such I need to use Guid
s so there aren't conflicts with Ids.