Как настроить StructureMap для использования универсального репозитория? - PullRequest
8 голосов
/ 14 мая 2010

У меня есть интерфейс 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

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

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

Simon

Ответы [ 3 ]

8 голосов
/ 14 мая 2010

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

т.е:.

 ObjectFactory.Initialize(x =>
        {
            x.For(typeof(DbConnection)).Use(typeof(SqlConnection));
            x.For(typeof(IGenericRepository<>)).Use(typeof(GenericRepository<>));
        });
4 голосов
/ 06 октября 2011

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

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

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"

После прочтения поста Джереми Миллера Нежный быстрый старт (справа внизу) я обнаружил, что вы можете определить, какие аргументы передать в конструктор ваших зарегистрированных типов, т.е. мне нужно было передать в Connection Строка для конструктора класса 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 ... счастливых дней.

3 голосов
/ 14 мая 2010

Как выглядит ваш конструктор для GenericRepository<>?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...