I have an interface IGenericRepository<TEntity> where TEntity : IEntity
and an implementation GenericRepository<TEntity> where TEntity : Entity
.
I'm trying to inject a specific IGenericRepository<Section>
into a class using StructureMap:
ObjectFactory.Initialize(x =>
{
x.For(typeof(IGenericRepository<>)).Use(typeof(GenericRepository<>));
});
But when I try to use ObjectFactory.GetInstance<IGenericRepository<Section>>();
I get:
StructureMap Exception Code: 202 No Default Instance defined for PluginFamily System.Data.Common.DbConnection
Any ideas why this is or what I'm doing wrong?
Thanks in advance,
Simon
You are receiving in your GenericRepository's constructor a DbConnection, which is an abstract class, and are not configuring SM to know which specific class should use for it.
i.e.:
ObjectFactory.Initialize(x =>
{
x.For(typeof(DbConnection)).Use(typeof(SqlConnection));
x.For(typeof(IGenericRepository<>)).Use(typeof(GenericRepository<>));
});
I had this exact same problem:
Have a Generic Repository:
public interface IRepository<TEntity> : IDisposable where TEntity : class
{ }
and a Concrete Implementation:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{ }
which i wanted injected into the constructor of the Controllers at runtime where the TEntity would be the Model relevant to that Controller:
public FooBarController(IRepository<FOO_BAR_TYPE> repository)
{
_repo = repository;
}
the Controller would then use Repository "_repo" to update the 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 elluded to the answer for me: had to add the ObjectContext to the StructureMap configuration (the Repository's purpose was to wrap up the Context generated by EntityFramework, which i called MyContextWrapper. Therefore because the Repository depended on MyContextWrapper, which in turn depends on 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
However, now i get the StructureMap runtime Exception:
StructureMap Exception Code: 205 Missing requested Instance property "connectionString"
After reading a post by Jeremy Miller A Gentle Quickstart (right at the bottom) i found that you can define what arguments to pass into the constructor of your registered types ie i needed to pass in the Connection String to the Constructor of the MyCustomContext class (here is the full listing of how i am initializing the 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");
});
And BOOM! Can now have my Controller instaniated at runtime by StructureMap and get it to inject an instance of IRepository...happy days.
What is your constructor like for GenericRepository<>
?
It or one of its dependencies is expecting a DbConnection
that SM can't create.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With