I am using WPF with Entity Framework 6 (DB first), Caliburn.Micro, and MEF.
I am trying to implement IoC in my project. I am an absolute beginner in IoC, and unfortunately, I cant find too many examples where MEF is used with Repository Pattern.
So I have a few repositories, and I have created my Generic Unit of Work like this:
class GenericUoW : IUoW, IDisposable
{
protected readonly DbContext _ctx;
public GenericUoW(DbContext context)
{
_ctx = context;
}
public void Complete()
{
_ctx.SaveChanges();
}
public void Dispose()
{
_ctx.Dispose();
}
}
My actual Unit of Work classes are implemented like this:
class InvoiceUoW : GenericUoW, IInvoiceUoW
{
public InvoiceUoW(DbContext _ctx) : base(_ctx)
{
salesrepo = new SaleRepository(_ctx);
itemsrepo = new ItemRepository(_ctx);
materialrepo = new MaterialRepository(_ctx);
raterepo = new RateRepository(_ctx);
clientrepo = new ClientRepository(_ctx);
taxrepo = new TaxRepository(_ctx);
stockhistoryrepo = new StockHistoryRepository(_ctx);
proformarepo = new ProformaRepository(_ctx);
}
public ISaleRepository salesrepo { get; private set; }
public IItemRepository itemsrepo { get; private set; }
public IMaterialRepository materialrepo { get; private set; }
public IRateRepository raterepo { get; private set; }
public IClientRepository clientrepo { get; private set; }
public ITaxRepository taxrepo { get; private set; }
public IStockHistoryRepository stockhistoryrepo { get; private set; }
public IProformaRepository proformarepo { get; private set; }
}
Now, in my ViewModel, I am doing something like this:
[Export(typeof(InvoiceViewModel))]
class InvoiceViewModel : PropertyChangedBase
{
#region ctor
[ImportingConstructor]
public InvoiceViewModel(IInvoiceUoW invoiceUoW)
{
_uow = invoiceUoW;
Clients = new BindableCollection<Client>(_uow.clientrepo.FetchAll());
}
#endregion
private readonly IInvoiceUoW _uow;
//other properties and methods
}
My question is related to the use of IoC/DI in InvoiceUoW. How do I implement constructor injection in that class? Because each of those repositories in that class has to be instantiated with the same DataContext. How do I make the DataContext a singleton? Please do note that I have several Unit of Work classes, each for one viewmodel.
Register the DbContext instance to be resolved and act like a singleton:
var container = new CompositionContainer(); //Get it from where it belongs
var dbContext = container.GetExportedValue<DbContext>();
container.ComposeExportedValue<DbContext>(dbContext);
For your UoW, MEF doesn't work the same way as Unity, in MEF you rather decorate the implementing type to tell the container it should register it:
[Export(typeof(IUnitOfWork))]
public class MyUnitOfWork : IUnitOfWork
Related
I am registering multiple components for a service and I want to provide additional metadata to the components that I can get without resolving the service.
With Microsoft extensibility framework you can provide your exports with additional metadata as seen here MEF Metadata and Metadata Views, is there something similar in Windsor?
I am currently trying to wrap my component in a class with 2 properties, IMetadata and Lazy where the lazy would resolve the component when needed.
public class Program
{
public static void Main(string[] args)
{
var container = new WindsorContainer();
// register the wrapped object that contains the Component metadata and a lazy to resolve the component
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.Configure(config =>
{
// create wrapper
var wrapper = new WrappedComponent();
wrapper.ComponentImpl = new Lazy<IService>(() => container.Resolve<IService>(config.Name));
// add metadata to the wrapper
if (config.Implementation.IsDefined(typeof(ComponentMetadataAttribute), false))
{
var metadata = (IComponentMetadata)config.Implementation.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)[0];
wrapper.Metadata = metadata;
}
// set the component to the wrapper
config.Instance(wrapper);
})
// also set service to wrapper
.WithService.Select((impl, services) => new List<Type>() { typeof(WrappedComponent) }));
// register the components
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>().Configure(config =>
{
if (config.Implementation.IsDefined(typeof(ComponentMetadataAttribute), false))
{
var metadata = (IComponentMetadata)config.Implementation.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)[0];
config.Named(metadata.Name);
}
}));
}
}
public class WrappedComponent
{
public IComponentMetadata Metadata { get; set; }
public Lazy<IService> ComponentImpl { get; set; }
}
[ComponentMetadata]
public class MyComponent : IService
{
public void Operation()
{
// Do stuff
}
}
public interface IService
{
void Operation();
}
public class ComponentMetadataAttribute : Attribute, IComponentMetadata
{
public string Name { get; set; }
public string Description { get; set; }
public string SomeOtherMetadata { get; set; }
}
public interface IComponentMetadata
{
string Name { get; set; }
string Description { get; set; }
string SomeOtherMetadata { get; set; }
}
You can make your WrappedComponent more generic and simplify your registrations by handling off the extraction of the metadata and lazy loaded component to the WrappedComponent class.
WrappedComponent takes the IKernel (from Castle Windsor) and uses it to determine the implementing type of the TComponent service from which metadata is retrieved. It also uses the IKernel to initialise the Lazy object. Remembering to handle the release of the TComponent as we're explicitly resolving it.
public class WrappedComponent<TComponent> : IDisposable
{
private readonly IKernel kernel;
public WrappedComponent(IKernel kernel)
{
this.kernel = kernel;
var componentType = this.kernel.GetHandler(typeof(TComponent)).ComponentModel.Implementation;
this.Metadata = componentType.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)
.Cast<ComponentMetadataAttribute>().FirstOrDefault();
this.ComponentImpl = new Lazy<TComponent>(() => this.kernel.Resolve<TComponent>());
}
public IComponentMetadata Metadata { get; }
public Lazy<TComponent> ComponentImpl { get; }
public void Dispose()
{
if (this.ComponentImpl.IsValueCreated)
{
this.kernel.ReleaseComponent(this.ComponentImpl.Value);
}
}
}
Registration becomes as simple as...
container.Register(Component.For(typeof(WrappedComponent<>)).LifestyleTransient());
container.Register(Classes.FromThisAssembly().BasedOn<IService>().WithService.FromInterface().LifestyleTransient());
I've assumed a Transient lifestyle, but whichever lifestyle you use, it'll be best to use the same for the WrappedComponent and IService.
IService, MyComponent, ComponentMetadataAttribute and IComponentMetadata remain unchanged.
Im doing an MVC 5 proyect using DI with IoC (Autofac) and the use of Generic Repository for the Data access part.
Now, my controller have an interface as a property injected to it called IProg_II_ModelFactory, this is the concrete class in question:
public class Prog_II_ModelFactory : IProg_II_ModelFactory
{
#region Fields
private readonly IGenericRepository<T> _genericRepository;
#endregion
#region Ctor
public Prog_II_ModelFactory(
IGenericRepository<T> genericRepository
)
{
_genericRepository = genericRepository;
}
#endregion
#region Methods
public Prog_II_Model SetProgIIModelStartUp()
{
var model;
model.FillList = _genericRepository.GettAll();
//Other things to be filled.
return model;
}
}
And my controller is injecting the interface of this class, here is the controller:
public class HomeController : Controller
{
private readonly IProg_II_ModelFactory _prog_II_ModelFactory;
public HomeController(
IProg_II_ModelFactory prog_II_ModelFactory
)
{
_prog_II_ModelFactory = prog_II_ModelFactory;
}
public ActionResult Index()
{
var model = _prog_II_ModelFactory.SetProgIIModelStartUp();
return View(model);
}
}
The problem with this is that Prog_II_ModelFactory must be generic (Prog_II_ModelFactory<T> where T : class)
The problem with this is that, it wont stop there, then it will ask me that the controller should also be generic and on top of that as Im using Autofac, the partial class to for the binding must be generic too and the App_Start itself!.
Is there any way I can use the Generic Interface of My repository without to flow TEntity all the way to App_Start ?
I read that I can use a method? but a lot of people is against this.
Edit:
Maybe instead of the property being Out of T, I have to type it?
for example:
#region Fields
private readonly IGenericRepository<Student> _genericRepository_Student;
private readonly IGenericRepository<Teacher> _genericRepository_Teacher;
#endregion
#region Ctor
public Prog_II_ModelFactory(
IGenericRepository<Student> genericRepository_Student,
IGenericRepository<Teacher> genericRepository_Teacher
)
{
_genericRepository_Student = genericRepository_Student;
_genericRepository_Teacher = genericRepository_Teacher;
}
#endregion
This means I cant do it at runtime, I have to know to which entity at compile time, what if I have 20 tables.
Edit 2:
This is my Model:
namespace Prog_II.Models
{
public class Prog_II_Model
{
#region Fields
public StudentModel Student{ get; set; }
public List<TurnModel> Turns{ get; set; }
public List<CarrerModel> Carrers { get; set; }
public List<StudentModel> Students{ get; set; }
#endregion
#region Ctor
public Prog_II_Model(){}
#endregion
}
public class StudentModel
{
#region Fields
public string Name { get; set; }
public string LastName{ get; set; }
public string NumberId { get; set; }
public string Carrer { get; set; }
public string Turn { get; set; }
#endregion
}
public class TurnModel
{
public string Description{ get; set; }
}
public class CarrerModel
{
public string Description{ get; set; }
}
}
And sure enough I pass a Prog_II_Model in my view:
#using Prog_II.Models
#model Prog_II_Model
public HomeController(Prog_II_ModelRepository modelRepository)...
public class Prog_II_ModelRepository()
{
IGenericRepository<Student> _genericRepository_Student; // get from somewhere
public Prog_II_Model GetModel()
{
var model = new Prog_II_Model();
model.Student = _genericRepository_Student.Get(); // some student
// put the rest of data into your huge all-encompassing model
return model;
}
}
That's just the idea - if you put all your data in a single model object, type-specific repositories are useful inside this single model repo, but it itself has no need to be generic (as opposed to general :)
I think there's something wrong with this One Huge Model approach, but YMMV.
Is your HomeController supposed to handle multiple entity types (Student, Teacher, Janitor, Dog, Cat, ...)? Is your Model flexible enough to handle all and any of them? If yes, use a non-generic repository interface, returning an object or some base entity type. If no, and you have different models per entity type (Dog has Color and Student has Scores), then your domain model asks for controller-per-entity type, inherited, as you said, from a generic controller type.
I don't see any reason for App_Start to be generic.
What is the best practice, following DI, to create two separate repository classes...e.g.
public class FirstDbRepo : Repository
public class SecondDbRepo : Repository
That essentially implement the Repository class shown below
namespace MyApp.Persistence
{
public class Repository<T> : IRepository<T> where T : EntityBase
{
public IConfig Config { get; set; }
private Database Database
{
get
{
// Use Config to get connection
};
set;
}
public Repository(IConfig config)
{
Config = config;
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
{
// Use database to get items
}
public T CreateItem(T item)
{
// Use database to create item
}
}
}
But to inject different config values/instances...
public interface IConfig
{
string DatabaseName{ get; }
string DatabaseEndpoint{ get; }
string DatabaseAuthKey{ get; }
}
The first thing I thought of was to create marker interfaces, but wanted to know if this smells...is there a more correct way to do this using DI?
public interface IFirstDbRepo { }
public class FirstDbRepo<T> : Repository<T> where T: EntityBase
{
public FirstDbRepo(FirstConfig config)
: base(config)
{ }
}
public class FirstConfig : IConfig
{
public string DatabaseName{ get { return "MyName" }; } // From web.config
}
And then use a ninject binding for each repo...the consumer could use as follows
public class Consumer() {
private readonly IFirstDbRepo _firstRepo;
public Consumer(IFirstDbRepo firstRepo) {
_firstRepo = firstRepo;
}
}
Bind<IConfig>().To<MyConfigOne>().WhenInjectedInto(typeof(FirstDbRepo));
Bind<IConfig>().To<MyConfigTwo>().WhenInjectedInto(typeof(SecondDbRepo ));
Contextual binding
I have an entity class
public partial class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
}
and this entity
public partial class User
{
public User()
{
this.Tokens = new HashSet<Token>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Name { get; set; }
public virtual ICollection<Token> Tokens { get; set; }
}
I have a repository pattern
public abstract class DataRepositoryBase<T> : IDataRepository<T>
where T : class, new()
{
protected abstract T AddEntity(T entity);
protected abstract T UpdateEntity(T entity);
protected abstract IEnumerable<T> GetEntities();
protected abstract T GetEntity(int id);
}
How can I call repository using generic data repository using some thing like this.<T> just using generic interface not creating new class? Thanks.
_datarepositorypattern.GetDataRepository<IProductRepository>();
_datarepositorypattern.GetDataRepository<IUserRepository>();
what i want, somthing like this.
var obj = _datarepositorypattern.GetDataRepository<IDataRepository<User>>();
//then i can access use
obj.GetEntities();
update
I already created repository
this repository can return
public DataRepositoryBase<Product> ProductRepository => new ProductRepository();
in the service class
private readonly UnitOfWork _unitOfWork;
public ProductServices(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
Product[] IProductServices.GetProduct()
{
var repository = _unitOfWork.ProductRepository;
return repository.Get().ToArray();
}
i use this current repository method like this.
what i wanted create dynamic repository so i do not updating my repository again only updating my service class with code like this.
var obj = _datarepositorypattern.GetDataRepository<IProductRepository>();
obj.GetEntities();
just using repository repository pattern i can get dynamic repository product
var obj = _datarepositorypattern.GetDataRepository<IUserRepository>();
obj.GetEntities();
just using repository repository pattern i can get dynamic repository User.
UPDATE
I just googling this is an repositoryfactorypattern can anyone help me.
as you've written it here you need you need new classes. You specify the IProductRepository and IUserRepository
that means you need something like
class UserRepository : DataRepositoryBase<User>, IUserRepository
{
//userrepository code here
}
otherwise you would get something like
_datarepositorypattern.GetDataRepository<IDataRepository<User>>();
expecially since your datarepository class is abstract you need a concrete implementation somewhere
Update: example not using entity specific repositories
If you really want to avoid entity specific repositories you can look at breeze.
you still need something like theis
class MyContext : DbContext {
DbSet<Product> Products {get; set;}
DBSet<User> Users {get; set;}
}
but then you can call a context provider like this
public class DataRepositoryBase<T> : IDataRepository<T> {
readonly EFContextProvider<User> _contextProvider =
new EFContextProvider<User>();
public void SaveEntity(JObject saveBundle) {
_contextProvider.SaveChanges(saveBundle);
}
}
now you can just call new DataBaseObjectRepository() (or have that code in your GetDataRepository method)
maybe that is a place to start. You do need something like DbContext that tells you how to map different types to different tables.
There are 4 parameterized constructor of one of my service layer(ProductService).
And all of the 4 constructors are injected with different repository types.
public class ProductService : IProductService
{
private IUserDal<Users> mUserDal { get; set; }
private IItemDal<Item> mItemDal { get; set; }
private IRoleDal<Role> mRoleDal { get; set; }
private IBranchDal<Branch> mBranchDal { get; set; }
public ProductService (IUserDal<Users> userDal)
{
mUserDal = userDal;
}
public ProductService (IItemDal<Item> itemDal)
{
mItemDal = itemDal;
}
public ProductService (IRoleDal<Role> roleDal)
{
mRoleDal = roleDal;
}
public ProductService (IBranchDal<Branch> branchDal)
{
mBranchDal = branchDal;
}
}
And ProductService layer is use in some of the Controller classes.
I am registering this ProductService class to Bootstrapper.cs(Unity DI) file with all of its dependencies types.But it's not registering properly.Some of the examples are below :-
Type 1:
container.RegisterType<IUserDal<Users>, UserDal>();
container.RegisterType<IItemDal<Item>,ItemDal>();
container.RegisterType<IRoleDal<Role>,RoleDal>();
container.RegisterType<IBranchDal<Branch>,BranchDal>();
container.RegisterType<IProductService,ProductService>();
Type 2:
container.RegisterType<IProductService, ProductService>(new InjectionConstructor(typeof(IUserDal<Users>), typeof(IItemDal<Item>), typeof(IRoleDal<Role>), typeof(IBranchDal<Branch>)));
But none of the above types are working.Can anyone know how to register any service class with multiple repository types in Bootstrapper file ?