0
votes

As I exposed here, I would like to be able to query freely on the index without Orchard building the query for me.

I built a module, and inserted a copy of the SearchController, adding a new route... To override default Orchard behavior concerning the query, I had to create new implementations of : ISearchService, IIndexManager, ISearchBuilder, IIndexProvider. There are minor modifications from their default implementations, but they are needed.

That works as expected, but it currently override the default search too. This is because I used the same interfaces and autofac takes my implementations.

I would like to be able to leave the default implementation untouched (at url /Search), and add my implementation at url (/LuceneSearch for example)

I suppose I must tell Autofac to use my implementations only for my controller by creating a class that inherits the autofac Module class. Here is my problem : I don't know how to tell Autofac to use by default the Orchard Implementation, and just for my controller, use my implementation....

Another possibility is to create new interfaces, but it seems to me not really beautiful...

Can someone help me ? :)

3

3 Answers

1
votes

Metadata feature will help you here. Also you have to register your implementations with PreserveExistingDefaults() modifier to preserve orchard's implementations by default.

Update:

Orchard registers all dependencies from Autofac's IModule implementation and from Orchard's IDependency one. All magic happen in Orchard's ShellContainerFactory class. Since ISearchService inherits from IDependency your implementation is registered by Orchard which overwrites default one.
You have two ways here:

  1. Introduce your own empty interface IMySearchService which inherits from ISearchService. Implement and use it in your code where you need your implementation. Orchard will handle all registrations for your.
  2. Orchard registers all IDependency implementations with "Feature" Metadata in ShellContainerFactory.RegisterType method. You can read this metadata in your code and choose your implementation (see link to wiki above). Feature class contains all necessary information about your module.

Hope this will help you.

1
votes

A simpler method without dabbling with the intricacies of Autofac would be to use an IEnumerable<IInterface> variable in your controller/driver at url "/LuceneSearch" to hold all implementations of IInterface and choose which to consume.

For example, in order to consume your implementation of IIndexManager, you would put the following in your controller or driver

public class MyCustomPartDriver : ContentPartDriver<MyCustomPart> {
    private readonly IEnumerable<IIndexManager> _indexManagers;

    public MyCustomPartDriver(IEnumerable<IIndexManager> indexManagers) {
        _indexManagers = indexManager;
    }

    protected override DriverResult Display(MyCustomPart part, string displayType, dynamic shapeHelper) {
        //Use your implementation of IIndexManager
        var indexManager = _indexManagers.First(im => im is MyCustomIndexManager);

        //Get the ISearchBuilder from your implementation of IIndexManager
        var searchBuilder = indexManager.HasIndexProvider() ? indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search") : new NullSearchBuilder();

        //perform search on the indexing engine
        var contentItemIds = searchBuilder.
            .WithField("type", "MyCustomType").Mandatory().ExactMatch()
            .Parse("mycustompart-keyword", part.Keyword).Mandatory()
            .Search()
            .Select(h => h.ContentItemId)
            .ToList();

        //do stuff with the results returned and return a DriverResult using the ContentShape method. Well, you know the drill.
    }
}
0
votes

If you don't want to have autofac resolve your own implementation by default, then don't implement the public interface.