I'm working on integrating a legacy database with Asp.Net Zero. I created the model classes using EntityFramework Reverse POCO Generator in a separate Models class library project. I also reversed engineered the DbContext into a separate Data class library project. I would like to use the Data Onion framework for my repositories and unit of work. When I use the recommended IOC container Autofaq my Test Winform application works correctly.
However, the Web Project utilizes Castle.Windsor. I'm uncertain on how to do the wire-up.
I'm creating a new container called ClientDesktopContainer:
internal class ClientDesktopContainer : WindsorContainer
{
public ClientDesktopContainer()
{
RegisterComponents();
}
private void RegisterComponents()
{
var connectionstring = ConfigurationManager.ConnectionStrings["MyDbContext"].ConnectionString;
// Data Onion
Component.For<IDbContextFactory>().ImplementedBy<DbContextFactory>()
.DependsOn(new DbContextConfig(connectionstring, typeof(MyDbContext), new MigrateToLatestVersion(new Seeder())));
Component.For<IDbContextScope>().ImplementedBy<DbContextScope>();
Component.For<IDbContextScopeFactory>().ImplementedBy<DbContextScopeFactory>();
Component.For<IAmbientDbContextLocator>().ImplementedBy<AmbientDbContextLocator>();
Component.For<IDbContextReadOnlyScope>().ImplementedBy<DbContextReadOnlyScope>();
// Data Onion Unit of Work
Component.For<IRepositoryLocator>().ImplementedBy<RepositoryLocator>();
// Component.For<IRepositoryResolver>().ImplementedBy<CastleWindsorRepositoryResolver>();
Component.For<IUnitOfWorkFactory>().ImplementedBy<UnitOfWorkFactory>();
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>();
Component.For<IReadOnlyUnitOfWork>().ImplementedBy<IReadOnlyUnitOfWork>();
// Custom
Component.For<IRepository<Enrollment>>()
.ImplementedBy<BaseRepository<Enrollment, MyDbContext>>();
}
My application invocation code is Program:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IoC.Initialize(new ClientDesktopContainer());
var dbContextScopeFactor = IoC.Resolve<IDbContextScopeFactory>();
using (var dbReadOnly = dbContextScopeFactor.CreateReadOnly())
{
var context = dbReadOnly.DbContexts.Get<MyDbContext>();
var individuals = context.Enrollments.ToList();
foreach (var individual in individuals)
{
// do stuff
}
}
Application.Run(new ViewMain());
}
}
I created a static IOC:
public static class IoC
{
private static IWindsorContainer _container;
public static void Initialize(IWindsorContainer container)
{
_container = container;
}
public static T Resolve<T>()
{
try
{
return _container.Resolve<T>();
}
catch
{
throw;
}
}
}
The Data Onion documentation mentions registering a custom Resolver for IRepositoryResolver.
I created a CastleWindsorRepositoryResolver:
public class CastleWindsorRepositoryResolver : IRepositoryResolver
{
public IRepository<TEntity> Resolve<TEntity>() where TEntity : class
{
// TODO: Resolve wire-up goes here
throw new System.NotImplementedException();
}
}
I'm receiving a ComponentNotFoundExpection:
var dbContextConfig = new DbContextConfig[]
{
new DbContextConfig(
connectionString,
typeof(MyDbContext),
new MigrateToLatestVersion(new Seeder())
)
};
// Data Onion
Register(Component.For<IDbContextFactory>().ImplementedBy<DbContextFactory>()
.DependsOn(Dependency.OnValue<DbContextConfig[]>(dbContextConfig)));
Add call to Register
in:
internal class ClientDesktopContainer : WindsorContainer
{
public ClientDesktopContainer()
{
RegisterComponents();
}
private void RegisterComponents()
{
var connectionstring = ConfigurationManager.ConnectionStrings["MyDbContext"].ConnectionString;
/* HERE CALL TO REGISTER: */
this.Register(
// Data Onion
Component.For<IDbContextFactory>().ImplementedBy<DbContextFactory>()
.DependsOn(new DbContextConfig(connectionstring, typeof(MyDbContext), new MigrateToLatestVersion(new Seeder()))),
Component.For<IDbContextScope>().ImplementedBy<DbContextScope>(),
Component.For<IDbContextScopeFactory>().ImplementedBy<DbContextScopeFactory>(),
Component.For<IAmbientDbContextLocator>().ImplementedBy<AmbientDbContextLocator>(),
Component.For<IDbContextReadOnlyScope>().ImplementedBy<DbContextReadOnlyScope>(),
// Data Onion Unit of Work
Component.For<IRepositoryLocator>().ImplementedBy<RepositoryLocator>(),
// Component.For<IRepositoryResolver>().ImplementedBy<CastleWindsorRepositoryResolver>(),
Component.For<IUnitOfWorkFactory>().ImplementedBy<UnitOfWorkFactory>(),
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>(),
Component.For<IReadOnlyUnitOfWork>().ImplementedBy<IReadOnlyUnitOfWork>(),
// Custom
Component.For<IRepository<Enrollment>>()
.ImplementedBy<BaseRepository<Enrollment, MyDbContext>>() );
}
Without Register
you are just creating registration object without actually putting types in container. Another thing that may help, by default Castle will register components as singletons add LifestyleTranscient
or PerWebRequest
to your UnitOfWork registrations.