1
votes

The Problem:

I am having trouble getting StructureMap to find the default instance for the IRepository<> type in the MongoRepostiory namespace.

The exception message:

"StructureMap Exception Code: 202 No Default Instance defined for PluginFamily MongoDB.Driver.MongoUrl, MongoDB.Driver, Version=1.8.3.9, Culture=neutral, PublicKeyToken=f686731cfb9cc103"

It appears that StructureMap is instantiating the MonogoRepository class with the wrong constructor...

The MonogoRepository has the following constructors:

    public class MongoRepository<T> : MongoRepository<T, string>, IRepository<T>, IRepository<T, string>, IQueryable<T>, IEnumerable<T>, IQueryable, IEnumerable where T : MongoRepository.IEntity<string>
{
    public MongoRepository();
    public MongoRepository(MongoUrl url);
    public MongoRepository(string connectionString);
    public MongoRepository(MongoUrl url, string collectionName);
    public MongoRepository(string connectionString, string collectionName);
}

I want the public MongoRepository(string connectionString); constructor to be called...but it appears that from the exception message, since StructureMap is attempting to resolve MongoUrl, it is not calling the desired one.

I wonder:

Questions:

  1. Have I setup something wrong which is causing the incorrect constructor to be called? or
  2. Is this the default behaviour, and if so, how do I change it to ensure the desired constructor is called?

The Setup:

I have the following Registry class:

public class IocRegistry : Registry
{
    public IocRegistry() 
    {
        this.For(typeof(IRepository<>)).Use(typeof(MongoRepository<>))
                            .CtorDependency<string>("connectionString")
                            .Is("MongoServerSettings");
    }
}

And the following Container initialization:

public static IContainer Initialize() {
        ObjectFactory.Initialize(x =>
                    {
                        x.Scan(scan =>
                                {
                                    scan.TheCallingAssembly();
                                    scan.LookForRegistries();
                                    scan.WithDefaultConventions();
                                });
                    });

        return ObjectFactory.Container;
    }

The IocRegistry is definitely getting hit when I put a break-point in its constructor and debug the application.

The code which consumes the IRepository<> is:

public class ImageContentService : IImageContentService
{
    private IRepository<ImageItem> imageRepository;

    public ImageContentService(IRepository<ImageItem> imageRepository) 
    {            
        this.imageRepository = imageRepository;
    }
}

The relevant output of ObjectFactory.Container.WhatDoIHave() (once all registrations have taken place) is:

===========================================================================================================
Configuration Sources:

0)   Registry:  StructureMap.InitializationExpression, StructureMap, Version=2.6.4.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223
1)   Registry:  StructureMap.Configuration.DSL.Registry, StructureMap, Version=2.6.4.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223
2)   Registry:  StructureMap.Configuration.DSL.Registry, StructureMap, Version=2.6.4.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223
3)   Registry:  Mch.Core.IocRegistry, Mch.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null


============================================================================================================================================================================================================================================================================================================================================
PluginType                                                                            Name                                                                                                            Description                                                                                                                           
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IRepository`1<T> (IRepository`1<T>)                                                   d26c76dd-8550-4d02-bf8a-25c6f0075346                                                                            Configured Instance of MongoRepository.MongoRepository`1, MongoRepository.Net45, Version=1.6.2.0, Culture=neutral, PublicKeyToken=null
Scoped as:  Transient

                                                                                      d26c76dd-8550-4d02-bf8a-25c6f0075346                                                                            Configured Instance of MongoRepository.MongoRepository`1, MongoRepository.Net45, Version=1.6.2.0, Culture=neutral, PublicKeyToken=null
2
Whats the output of ObjectFactory.Container.WhatDoIHave() ? - ozczecho
I have added the output of ObjectFactory.Container.WhatDoIHave() - JTech

2 Answers

1
votes

You can tell StructureMap which constructor to use:

x.SelectConstructor<ClassWithTwoConstructors>(()=>new ClassWithTwoConstructors(0));

You can find this in the StructureMap documentation.

0
votes

I had the exact same issue. In the end I solved it by configuring my MongoRepository in the ObjectFactory initialisation like so:

x.For<IRepository<T>>().Use(() => new MongoRepository<T>("{ConnectionString}","{CollectionName}"));

This way it seems the Structuremap seems to use the correct constructor. Obviosuly you can instantiate the MongoRepository with whichever constructor you prefer.