如何配置StructureMap以使用通用存储库?

时间:2010-05-14 15:35:44

标签: c# generics dependency-injection structuremap

我有一个界面IGenericRepository<TEntity> where TEntity : IEntity和一个实现GenericRepository<TEntity> where TEntity : Entity

我正在尝试使用StructureMap将特定的IGenericRepository<Section>注入到类中:

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

但是当我尝试使用ObjectFactory.GetInstance<IGenericRepository<Section>>();时,我得到了:

StructureMap异常代码:202没有为PluginFamily System.Data.Common.DbConnection定义默认实例

为什么会这样或者我做错了?

提前致谢,

西蒙

3 个答案:

答案 0 :(得分:8)

您在GenericRepository的构造函数中收到一个DbConnection,它是一个抽象类,并没有配置SM来知道应该使用哪个特定类。

即:

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

答案 1 :(得分:4)

我有同样的问题:

拥有通用存储库:

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

和具体实施:

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

我想在运行时注入Controllers的构造函数,其中TEntity将是与该Controller相关的模型:

public FooBarController(IRepository<FOO_BAR_TYPE> repository)
        {
            _repo = repository;
        }
然后,Controller将使用Repository“_repo”来更新Model:

//
// 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配置中(Repository的目的是包装由EntityFramework生成的Context,我称之为MyContextWrapper。因此,Repository依赖于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”

在阅读Jeremy Miller A Gentle Quickstart的帖子后(右下方)我发现你可以定义传入你注册类型的构造函数的参数,即我需要将连接字符串传递给构造函数的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"); 
            });

和BOOM!现在可以让我的Controller在运行时由StructureMap实现,并让它注入一个IRepository实例......快乐的日子。

答案 2 :(得分:3)

你的构造函数是什么样的GenericRepository<>

它或其中一个依赖项期望SM无法创建DbConnection