views:

82

answers:

1

We have the following interface that we use to define how an entity should be indexed (using lucene):

public interface IIndexDefinition<T> where T : IIndexable {
    Document Convert(T entity);
}

This means we can keep our index service very simple. So to index an entity we have:

   IndexResult IndexEntities<TEntity>(IEnumerable<TEntity> entities, 
                                      IIndexDefinition<TEntity> definition) 
                                                    where TEntity : IIndexable;

To support incremental updates to the index we have created an index queue. The index queue contains a thread safe list of tasks to perform against the lucene index.

Essentially an IndexTask is just a means of storing the updated entity and the index definition. The class we have currently is:

public class IndexTask<TEntity>
{
    private TEntity entity;
    private IIndexDefinition<TEntity> definition;

    public IndexTask(TEntity entity, IIndexDefinition<TEntity> definition)
    {
        this.entity = entity;
        this.definition = definition;
    }

    public TEntity Entity { get { return this.entity; } }
    public IIndexDefinition<TEntity> Definition { get { return definition; } }
}

When an entity is updated we will have the following in our event handler:

        var task = new IndexTask<Car>(car, new CarIndexDefinition());
        IndexQueue.Instance.AddItem(task); // this doesn't work

And to execute the tasks in the queue:

        var tasks = IndexQueue.Instance.Items;

        var service = new IndexService();

        foreach (var task in tasks) {
            service.IndexEntity(task.Entity, task.Definition);
        }

My question is how I can create a list of generic IndexTask<TEntity> objects on the IndexQueue, and cast out to the relevant entity type when I execute the task.

Since my entities implement the IIndexable interface I could store a list of IndexTask<IIndexable> but this will result in "task.Definition" resolving to IIndexDefinition<IIndexable> in the above code.

Thanks Ben

Update

I thought about exposing the following on a base class for index task "IndexTaskBase":

    public abstract Type GetEntityType();
    public abstract Type GetDefinitionType();

and then overriding on IndexTask:

    public override Type GetEntityType() {
        return this.entity.GetType();
    }

    public override Type GetDefinitionType() {
        return this.definition.GetType();
    }

If I store a list of IndexTaskBase on the queue, could I then convert my types using these methods - perhaps using System.ComponentModel.TypeConverter?

+1  A: 

Could you rewrite:

service.IndexEntity(task.Entity, task.Definition);

To the following on a method of task:

task.IndexWithService(service);

Then, inside the IndexWithService, you can do:

service.IndexEntity(this.Entity, this.Definition);

The IndexWithService could be implemented on a base class of Task that is not a generic and the list can be of that type.

Pieter
This is exactly what I ended up doing (well I used an IIndexTask interface instead of using an abstract class). Amazing what a few hours away from the computer can do!
Ben