In my project, I have the following PageCache entity, which is being stored in RavenDB:
public class PageCache
{
private readonly IHtmlDocumentHelper htmlDocumentHelper;
public string Id { get; set; }
public string Url { get; set; }
public PageCache(IHtmlDocumentHelper htmlDocumentHelper, string url)
{
this.htmlDocumentHelper = htmlDocumentHelper;
this.Url = url;
}
}
I am using Castle Windsor to inject the IHtmlDocumentHelper implementation at runtime. This member is used in methods defined inside the PageCache class, which I stripped from the above snippet for the sake of simplicity.
When I create a PageCache object using the constructor, everything works fine. But elsewhere in my code, I load PageCache objects back from RavenDB:
public PageCache GetByUrl(string url)
{
using (var session = documentStore.OpenSession())
{
return session.Query<PageCache>()
.Where(x => x.Url == url)
.FirstOrDefault();
}
}
My issue is that the objects I get back from RavenDB don't have the htmlDocumentHelper member set, rendering the PageCache methods that depend on it unuseable.
In other words: when I load objects back from documents stored in RavenDB, it won't use my constructor to build the objects, thus not initializing the private members through constructor injection.
Am I doing something wrong here? How would you solve such an issue?
I ended up using the solution proposed by Ayende below. The circular dependency issue I mentioned in the comments only appeared when I registered the DocumentStore in Windsor with UsingFactoryMethod(). The issue strangely disappeared when I used Windsor's DependsOn() and OnCreate() to configure and initialize the DocumentStore directly inside the Register().
My container is now being initialized as follows:
WindsorContainer container = new WindsorContainer();
container.Register(
// Register other classes, such as repositories and services.
// Stripped for the sake of clarity.
// ...
// Register the CustomJsonConverter:
Component.For<CustomJsonConverter>().ImplementedBy<CustomJsonConverter>(),
// The following approach resulted in an exception related to the circular
// dependencies issue:
Component.For<IDocumentStore>().UsingFactoryMethod(() =>
Application.InitializeDatabase(container.Resolve<CustomJsonConverter>()))
// Oddly enough, the following approach worked just fine:
Component.For<IDocumentStore>().ImplementedBy<DocumentStore>()
.DependsOn(new { Url = @"http://localhost:8080" })
.OnCreate(new Action<IDocumentStore>(store =>
store.Conventions.CustomizeJsonSerializer = serializer =>
serializer.Converters.Add(container.Resolve<CustomJsonConverter>())))
.OnCreate(new Action<IDocumentStore>(store =>
store.Initialize()))
.OnDestroy(new Action<IDocumentStore>(store =>
store.Dispose()))
);
Although it seems to be working fine, I feel odd having to call container.Resolve<CustomJsonConverter>() from inside the container.Register() method.
Is this a legal approach to register the dependencies?