Search code examples
c#inversion-of-controlioc-containerstructuremap

StructureMap Open Generic types with multiple types


so I've been trying to solve this issue for a couple of hours now. I searched the internet and looked at many Stackoverflow questions, but none could help me.


So I'm building a pipeline. The basic conecpt is the following:

  • PipelineStore (Singleton) - Contains all registered Pipeline
  • Pipeline[TEntity] (Transient) - One Pipelineper Entity (Account, Contact, ...)
  • PipelineStep[TOperation, TInteractor, TEntity] (Transient) - Many Steps per Pipeline

[] representing the generic types.


I want to use StructureMap to create the Pipeline and the PipelineStep. So I created an auto factory called IPipelineFactory which has a single function:

IPipeline<TEntity> CreatePipeline<TEntity>() TEntity : EntityDTO, new();

I registered it in the Registry:

For<IPipelineFactory>().CreateFactory();
For(typeof(IPipeline<>))
    .Use(typeof(Pipeline<>))
    .Transient();

Then I get the IPipelineFactory injected and use it like the following:

public IPipeline<TEntity> NewPipeline<TEntity>() 
    where TEntity : EntityDTO, new()
{
    var pipeline = _pipelineFactory.CreatePipeline<TEntity>();
    _pipelines.Add(pipeline);
    return pipeline;
}

This works great, but when I try to do the same thing with the PipelineStep it fails:

public interface IPipelineStepFactory
{
    IPipelineStep<TOperation, TInteractor, TEntity> CreatePipelineStep<TOperation, TInteractor, TEntity>() 
        where TOperation : IOperation<TInteractor, TEntity> 
        where TInteractor : IInteractor<TEntity>
        where TEntity : EntityDTO, new();
}

And the registration:

For<IPipelineStepFactory>().CreateFactory();
For(typeof(IPipelineStep<,,>))
    .Use(typeof(PipelineStep<,,>));

usage:

public IAddPipeline<TEntity> Pipe<TOperation, TInteractor>()
    where TOperation : IOperation<TInteractor, TEntity>
    where TInteractor : IInteractor<TEntity>
{
    var step = PipelineStepFactory.CreatePipelineStep<TOperation, TInteractor, TEntity>();
    RegisteredSteps.Add(step);
    return this;
}

When I try to test the code it throws the following exception at runtime:

No default Instance is registered and cannot be automatically determined for type 'IPipelineStep<TestOperation, ITestInteractor, TestEntity>'

There is no configuration specified for IPipelineStep<TestOperation, ITestInteractor, TestEntity>

I thinks it's probably missing support for open generic types with multiple type arguments. Please let me know if there's any workarround to fix this issue. Thanks for your time!


Solution

  • So I figured it out myself. The problem was, that the PipelineStep had slightly different generic type constraints which caused the issue. I changed

    public class PipelineStep<TOperation, TInteractor, TEntity> : PipelineStepBase, IPipelineStep<TOperation, TInteractor, TEntity> 
        where TOperation : IOperation<TInteractor, TEntity>, IOperation<IInteractor<EntityDTO>, EntityDTO>
        where TInteractor : IInteractor<TEntity>, IInteractor<EntityDTO>
        where TEntity : EntityDTO
    

    to

    public class PipelineStep<TOperation, TInteractor, TEntity> : PipelineStepBase, IPipelineStep<TOperation, TInteractor, TEntity> 
            where TOperation : IOperation<TInteractor, TEntity>
            where TInteractor : IInteractor<TEntity>
            where TEntity : EntityDTO
    

    and now it's working!