RavenDB and constructor injection

In my project, I have the following PageCache object that is 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 use Castle Windsor to implement the IHtmlDocumentHelper implementation at runtime. This element is used in methods defined inside the PageCache class, which I just removed from the above snippet for simplicity.

When I create the PageCache object using the constructor, everything works fine. But elsewhere in my code, I load PageCache objects from RavenDB:

 public PageCache GetByUrl(string url) { using (var session = documentStore.OpenSession()) { return session.Query<PageCache>() .Where(x => x.Url == url) .FirstOrDefault(); } } 

My problem is that the objects I return from RavenDB do not have a set of htmlDocumentHelper elements, providing PageCache methods that depend on this, are unused.

In other words: when I load objects back from documents stored in RavenDB, it will not use my constructor to assemble objects, thereby not initializing private members by injecting the constructor.

Am I doing something wrong here? How would you solve this problem?


In the end, I used the solution proposed by Ayende below. The circular dependency issue, which I mentioned in the comments, appeared only after registering the DocumentStore in Windsor using UsingFactoryMethod() . The problem strangely disappeared when I used Windsor DependsOn() and OnCreate() to configure and initialize the DocumentStore directly inside Register() .

My container is now 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, it seems strange to call container.Resolve<CustomJsonConverter>() from within the container.Register() method.

Is this a legal approach for registering dependencies?

+4
source share
1 answer

Christian, We can’t use your ctor, we don’t know what to put there.

Instead, you can use this technique to tell RavenDB how to create your objects: http://james.newtonking.com/projects/json/help/CustomCreationConverter.html

You can then bind this using documentStore.Conventison.CustomizeSerializer

+2
source

Source: https://habr.com/ru/post/1413272/


All Articles