Search code examples
c#nhibernatefluent-nhibernate

NHibernate - Perform step after retrieving database entry


I have a class that has some metadata attached to it. For example:

public class Parameter<T> : IParameter
{
    public string Id { get; set; }
    public T Value { get; set; }
    public List<IParameter> Metadata { get; set; }
}

I have another class which then contains a IList<IParameter>

public class Bar
{
    public IList<IParameter> Parameters { get; set; }
}

I have a IUserType which can store certain types as JSON (such as a List<IParameter>). I plan to store the Bar.Parameters using this, so the column value would look like:

[
    {
        "id": "letter",
        "value": "a",
        "metadata": [
            "options": [ "a", "b", "c" ]
        ]
    },
    {
        "id": "cat.name",
        "value": "Mittens",
        "metadata": [
            "display_name": "Name"
        ]
    }
]

However it is unnecessary for me to store the metadata, as it is defined elsewhere and can be retrieved using Parameter.Id. I would like to instead store an array of the ids mapped against their values:

[
    "letter": "a",
    "cat.name": "Mittens"
]

I know how to make the Parameters column be written in this way, but I am unsure how I could go about making Bar retrieve the metadata once it has been retrieved.

What would be ideal is the something similar to the OnDeserialized attribute in WCF. This lets me define a method on Bar that is called once it has been deserialized:

public class Bar
{
    public string Type { get; set; }
    public IList<IParameter> Parameters { get; set; }

    [OnDeserialized]
    private void OnDeserialized(StreamingContext ctx)
    {
        // Extremely simplified example of how the Foo metadata may
        // be retrieved.
        foreach(var parameter in Parameters)
        {
            parameter.Metadata = BarMetadataStore.GetMetadata(Type, parameter.Id);
        }
    }
}

I would like to avoid manually calling a function on Bar to retrieve the metadata as my real Bar is part of a large class hierarchy. NHibernate automagically retrieves a Bar as part of a join when I retrieve the owning class.

It is also important that Bar can perform the "deserialization" step, as other classes use the Parameter<T> class and may populate the metadata from a different place to Bar.

I was considering using an IUserType which loads the metadata in the NullSafeGet but the GetMetadata is dependent on another property of the Bar and I do not know how to get that value in all the necessary places.

In short: Is there something similar to [OnDeserialized] in NHibernate/FluentNHibernate?


Solution

  • I think event listeners (more specifically, IPostLoadEventListener) is what you're after.