views:

408

answers:

3

Essentially the title of this question explains the essense of what I am trying to do, but to create a contrived example...

I have a class, call it Employee. Employee has an IPaymentBehaviour...

public class Employee 
{
  IPaymentBehaviour _paymentBehaviour;

  protected internal Employee() { /* required by NH */}

  public Employee(IPaymentBehaviour paymentBehaviour)
  {
    _paymentBehaviour = paymentBehaviour;
  }

}

This corresponds to a database table like so:

dbo.Employees
-> EmployeeId (primary key)
-> PaymentBehaviourId (foreign key to lookup table)
-> Field1
-> Field2
-> Field3
-> Field4

Depending on the value of PaymentBehaviourId I need to 'inject' a different implementation of IPaymentBehaviour into the Employee object. Depending on which PaymentBehaviour was in use, Field1, 2, 3 or 4 might be needed to create that behaviour.

Can anyone tell me how this would be mapped using Fluent-NHibernate?

+1  A: 

NHibernate uses the default constructor to instantiate entities. There are some workarounds though.

Darin Dimitrov
A: 

I think I would work around it like this:

  • Create a default constructur on the Employee object , that has a private access modifier, so that NHibernate can reconstruct those types
  • Create an Interceptor in where you overload the appropriate methods (OnLoad I presume), in which you make sure that you inject the correct IPaymentBehaviour implementation into the entity. (Perhaps you can create an interface 'IPaymentBehaviourInjectable' that can be implemented by the Employee class (implement it explicitily), so that you can inject the correct behaviour into the entity ...
Frederik Gheysels
+1  A: 

table Employees

  • EmployeeId (primary key)
  • PaymentBehaviourId (foreign key to PaymentBehaviour)

table PaymentBehaviour

  • PaymentBehaviourId (pk)
  • type (discriminator)
  • Field1
  • Field2
  • Field3
  • Field4

Classes

public class Employee 
{
  /* ... */  
  public PaymentBehaviour PaymentBehaviour { get; set; }
}

public class PaymentBehaviourA : IPaymentBehaviour
{
  /* ... */  
  public int Field1 { get; set; }
}

public class PaymentBehaviourB : IPaymentBehaviour
{
  /* ... */  
  public int Field2 { get; set; }
}

I don't know FluentNHibernate enough to tell you how it looks like, but in XML you would specify it like this:

<class name="Employee" table="Employees">
  <many-to-one name="PaymentBehaviour" class="IPaymentBehaviour">
</class>

<class name="IPaymentBehaviour" abstract="true" >
  <discriminator column="type"/>

  <subclass name="PaymentBehaviourA" discriminator-value="A">
    <propert name="Field1"/>
  </subclass>

  <subclass name="PaymentBehaviourB" discriminator-value="B">
    <propert name="Field2"/>
  </subclass>
</class>
Stefan Steinegger