Как мне настроить StructureMap для использования общего репозитория?

У меня есть интерфейс IGenericRepository<TEntity> where TEntity : IEntity и реализация GenericRepository<TEntity> where TEntity : Entity.

Я пытаюсь ввести конкретный IGenericRepository<Section> в класс с помощью StructureMap:

    ObjectFactory.Initialize(x =>
        {
            x.For(typeof(IGenericRepository<>)).Use(typeof(GenericRepository<>));
        });

Но когда я пытаюсь использовать ObjectFactory.GetInstance<IGenericRepository<Section>>();, я получаю:

Код исключения StructureMap: 202 Экземпляр по умолчанию для PluginFamily System.Data.Common.DbConnection не определен

Есть идеи, почему это так или что я делаю не так?

Заранее спасибо,

Саймон


person simonjreid    schedule 14.05.2010    source источник


Ответы (3)


Какой у вас конструктор для GenericRepository<>?

Он или одна из его зависимостей ожидает DbConnection, который SM не может создать.

person Andrew Bullock    schedule 14.05.2010
comment
Спасибо за это, мой общий репозиторий принимает ObjectContext, который я не добавил через SM. - person simonjreid; 17.05.2010
comment
Это ответ или другой вопрос? Если это вопрос, почему он отмечен как принятый ответ? - person Ken Burkhardt; 31.10.2011

Вы получаете в своем конструкторе GenericRepository объект DbConnection, который является абстрактным классом, и не настраиваете SM, чтобы знать, какой конкретный класс следует использовать для него.

i.e.:

 ObjectFactory.Initialize(x =>
        {
            x.For(typeof(DbConnection)).Use(typeof(SqlConnection));
            x.For(typeof(IGenericRepository<>)).Use(typeof(GenericRepository<>));
        });
person eglasius    schedule 14.05.2010

У меня была такая же проблема:

Иметь общий репозиторий:

public interface IRepository<TEntity> : IDisposable where TEntity : class
    { }

и конкретная реализация:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    { }

который я хотел ввести в конструктор контроллеров во время выполнения, где TEntity будет моделью, относящейся к этому контроллеру:

public FooBarController(IRepository<FOO_BAR_TYPE> repository)
        {
            _repo = repository;
        }

Затем Контроллер будет использовать Репозиторий «_repo» для обновления Модели:

//
// POST: /EmergencyServiceType/Create
[HttpPost]
public ActionResult Create(FOO_BAR_TYPE foobar)
{
    if (ModelState.IsValid)
    {            
        // GetNextSequenceValue() deals with Oracle+EF issue with auto-increment IDs
        foobar.FOO_BAR_ID = _repo.GetNextSequenceValue(); 
        _repo.Add(foobar);
        _repo.SaveChanges();
        return RedirectToAction("Index");  
    }

    return View(foobar); // display the updated Model
}

simonjreid озвучил для меня ответ: пришлось добавить ObjectContext в конфигурацию StructureMap (цель репозитория заключалась в том, чтобы завершить контекст, сгенерированный EntityFramework, который я назвал MyContextWrapper. Следовательно, поскольку репозиторий зависит от MyContextWrapper, который, в свою очередь, зависит от ObjectContext ):

// This avoids 'No Default Instance for ...DbConnection' exception
x.For<System.Data.Objects.ObjectContext>().Use<MyContextWrapper>();
x.For<System.Web.Mvc.IController>().Use<Controllers.FooBarController>().Named("foobarcontroller"); // note that Named is required and is Case Sensitive

Однако теперь я получаю исключение времени выполнения StructureMap:

Код исключения StructureMap: 205 Отсутствует запрошенное свойство экземпляра "connectionString"

Прочитав сообщение Джереми Миллера Быстрый старт (справа внизу), я обнаружил, что вы можете определить, какие аргументы передать в конструктор ваших зарегистрированных типов, т.е. мне нужно было передать строку подключения в конструктор класса MyCustomContext (вот полный список того, как я инициализирую ObjectFactory:

string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["MyContextWrapper"].ConnectionString;
ObjectFactory.Initialize(x =>
            {
                x.Scan(scan =>
                        {
                            // Make sure BUSINESS_DOMAIN assembly is scanned
                            scan.AssemblyContainingType<BUSINESS_DOMAIN.MyContextWrapper>(); 
                            scan.TheCallingAssembly();
                            scan.WithDefaultConventions();
                        });
                // 'connStr' below is a local variable defined above
                x.For<System.Data.Objects.ObjectContext>()
                    .Use<MyContextWrapper>()
                    .Ctor<string>().Is(connStr);
                x.For<System.Web.Mvc.IController>().Use<Controllers.FooBarController>().Named("foobarcontroller"); 
            });

И БУМ! Теперь можно создать экземпляр моего Контроллера во время выполнения с помощью StructureMap и заставить его внедрить экземпляр IRepository ... счастливых дней.

person HellspawnDeveloper    schedule 06.10.2011