Is my context too coupled with my repository? - c#

Learning Entity Framework, Repositories and IOC, what I am trying to achieve is to implement the repository pattern in order to change my data source provider.
Please see this example from an open-source project:
namespace MyApp.Domain.Interfaces
{
public interface IEFContext : IDisposable
{
}
}
EFContext (implementing IEFContext)
namespace MyApp.Data.Context
{
public class EFContext : DbContext, IEFContext
{
public const string DBConnectionName = #"MyDBName";
public EFContext() : base(DBConnectionName)
{
}
public DbSet<Member> Member { get; set; }
}
}
IMemberRepository
namespace MyApp.Domain.Interfaces.Repositories
{
public interface IMemberRepository
{
Member GetUser(string username);
}
}
MemberRepository (implementing IMemberRepository)
namespace MyApp.Data.Repositories
{
public class MemberRepository : IMemberRepository
{
private readonly EFContext _context;
public MemberRepository(IEFContext context)
{
_context = context as EFContext;
}
// update
public Member GetUser(string username)
{
return _context.Member.SingleOrDefault(name => name.UserName.ToUpper().Contains(username.ToUpper()));
}
}
}
and this is my application console using Unity
Console App
namespace MyApp.ConsoleApp
{
public class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<IEFContext, EFContext>();
container.RegisterType<IMemberRepository, MemberRepository>();
var repository = container.Resolve<MemberRepository>();
var user = repository.GetUser("johnDoe");
Console.WriteLine(user.Email);
Console.ReadLine();
}
}
}
My question is the following:
if I decide to add a new context, such as:
namespace MyApp.Data.Context
{
public class EFContext2 : DbContext, IEFContext
{
public const string DBConnectionName = #"MyNewDBName";
public EFContext2() : base(DBConnectionName)
{
}
public DbSet<Member> Member { get; set; }
}
}
I should have only to change the dependency like:
namespace MyApp.ConsoleApp
{
public class Program
{
static void Main(string[] args)
{
...
container.RegisterType<IEFContext, EFContext2>();
...
}
}
}
but in this example my MemberRepository is loosely-coupled with my first context. So if I have to change my Context I must also change my repository.
I would be please to have your point of view on this.
Kind regards

but in this example my MemberRepository is loosely-coupled with my first context. So if I have to change my Context I must also change my repository.
Yes it is, but it's a one line change from:
private readonly EFContext _context;
to
private readonly IEFContext _context;
And not casting on your constructor:
public MemberRepository(IEFContext context)
{
_context = context;
}
Now, you can inject any kind of concrete context that implements IEFContext.
Just think about this: What you're trying to do with dependency injection is, well, inject dependencies. But, how do you do that? Well, you do that by generalizating those dependencies. I mean, you want to be able to use different context, then you use an interface IEFContext instead of a concrete context. That's why your constructor expects an interface.
But, that's the first part, know, the problem with your code is that when you say
_context = context as EFContext;
You're downcasting the interface and saying: This interface is an EFContext. You're loosing the generality. Know when you try to inject a, say, SQLContext, you'll not be able since although it's and IEFContext it isn't an EFContext. That's why you remove the as EFContext part and just let
_context = context;
Now as for the second part, being general and expecting and receiving an interface is just the first part. You now need to tell the compiler that you're expecting a generic context IEFContext, but you need also tell him that no matter which context you receive you should be able to, say, GetUsers. That's where your interface comes into play. You know declare the property public Member GetUser{} within your interface forcing and guaranteeing then that no matter which context arrive you'll be able to get your users.
I hope this to be a little simple to understand. Good luck.

Related

Simple Injector in Console Application with multiple projects and an abstract factory

TL;DR. I have a circular dependency and no idea how to break it.
Main.csproj: has Program.cs which manually instantiates DiService
var diService = new DiService(new Container());
diService.Register();
The register method searches CurrentDomain for assemblies and registers collections where multiple implementations exist for a given interface or else registers concretions on a 1-1 basis.
It then uses the Container to instantiate an abstract factory.
var diFactory = diService.Registry.GetInstance<IDiFactory>();
Here's the factory
public class DiFactory : IDiFactory
{
private readonly Container registry;
public DiFactory(Container registry)
{
this.registry = registry;
}
public T Get<T>()
{
var reqT = typeof(T);
return (T) registry.GetInstance(reqT);
}
}
The project dependencies in the solution look like this:
Main -> A -> B,E
B -> C,D,E
C -> D,E
D -> E
DiService and DiFactory live in project B with the other services. Not that it matters. I think I'd have the same problem if they were in Main.
All objects in projects B to E have a constructor injected DiFactory so they can decide what objects they need at run time. But for C to make use of it, it must depend on B, which is a circular dependency.
If I move the DI stuff to a new project F, then all projects can depend on that but how does the factory reference the types in the other projects without creating another circular dependency?
I followed the documentation for IRequestHandler, I just didn't do the dictionary. Most likely I have a design flaw but I can't see what it is.
Here's an example of the interactions between objects for LinqPad - doesn't compile but it looks right.
void Main()
{
var diService = new Mine.Services.MyDiService();
var diFactory = diService.Container.GetInstance<Mine.Services.IMyFactory>();
var rand = new Random();
var next = rand.Next(1, 100);
var task = next % 2 == 0
? diFactory.Get<Mine.Tasks.EvenTask>()
: (Mine.Tasks.IMyTask)diFactory.Get<Mine.Tasks.OddTask>();
task.Perform();
}
namespace Mine.Common
{
public class MyCommonObject { }
}
namespace Mine.Services
{
public class FakeContainer
{
public T GetInstance<T>() { return default(T); }
}
public interface IMyOtherService { void DoSomethingElse(); }
public class MyOtherService : IMyOtherService
{
public void DoSomethingElse()
{
throw new NotImplementedException();
}
}
public class MyService
{
private readonly IMyFactory myFactory;
public MyService(IMyFactory myFactory)
{
this.myFactory = myFactory;
}
public void MyServiceMethod()
{
var thing = myFactory.Get<Mine.Common.MyCommonObject>();
}
}
public interface IMyFactory { T Get<T>(); }
public class MyDiService
{
public FakeContainer Container;
}
public class MyFactory : IMyFactory
{
private FakeContainer Container;
public MyFactory(FakeContainer container)
{
// obviously this is really a SImple Injector Container
Container = container;
}
public T Get<T>()
{
return default(T);
}
}
}
namespace Mine.Kernel {
public interface IMyMultiConcrete { void Do(); }
public class MyConcreteBase : IMyMultiConcrete
{
protected readonly Mine.Services.IMyFactory MyFactory;
public MyConcreteBase(Mine.Services.IMyFactory myFactory)
{
MyFactory = myFactory;
}
public void Do()
{
MyFactory.Get<Mine.Common.MyCommonObject>();
}
}
public class MyConcrete1 : MyConcreteBase
{
public MyConcrete1(Mine.Services.IMyFactory myFactory) : base(myFactory) {}
public void Do()
{
MyFactory.Get<Mine.Common.MyCommonObject>();
}
}
}
namespace Mine.Tasks
{
public interface IMyTask { void Perform(); }
public class TaskBase : IMyTask
{
protected readonly Mine.Services.IMyOtherService MyOtherService;
public TaskBase(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
{
MyOtherService = myOtherService;
}
public void Perform()
{
MyOtherService.DoSomethingElse();
}
}
public class OddTask : TaskBase
{
public OddTask(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
: base(myFactory, myOtherService) { }
}
public class EvenTask : TaskBase
{
public EvenTask(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
: base(myFactory, myOtherService) { }
}
}
This IDiFactory abstraction you are describing is not an implementation of the Abstract Factory design pattern—it is an implementation of the Service Locator pattern. Service Locator, however, is an anti-pattern and you should stop using it because its numerous downsides.
Instead, classes should not be able to request an unbound set of dependencies from a Service Locator, but neither should they typically be able to request a fixed set of dependencies using an Abstract Factory. Instead, classes should statically declare their required dependencies through the constructor.
This change might already fix the circular dependency as you will remove the IDiFactory (that is causing the cycle) in the first place.
DiService and DiFactory live in project B with the other services. Not that it matters.
It does matter where you wire up your dependencies. Dependencies should be wired up in your Composition Root and this Composition Root should live
As close as possible to the application’s entry point.
This most likely means that you should move this to your Console application. When you move that code, only the start-up assembly will take a dependency on the used DI Container. At that point, it becomes irrelevant to hide the DI Container behind an Abstraction (as your DiService seems to imply). Hiding is not needed anymore, because no other parts of the application except the Composition Root will have any knowledge about how dependency graphs are built. Hiding the DI Container behind an abstraction, at that point, doesn't increase maintainability any longer.
There might be an easier way, but what I typically end up doing is to have a separate assembly containing interfaces for everything I need to inject.
The main assembly (or B could do it in your case) performs the binding of interfaces to concrete implementations and everyone can reference the interfaces assembly without creating any circular dependencies.
The interface for the factory should also be in that assembly.

Resolving generic Decorators with Simple Injector

I am trying to build out a structure where I have a base IValidator<> interface that will be generated for our system based on some metadata. We want to give future developers the flexibility to 1) Regenerate the concrete implementations of IValidator<> if need be without disturbing any hand-written code and 2) Add decorators to IValidator<> to be able to extend the functionality without disturbing the auto-generated code.
I would like to have some way to resolve the generic decorators at runtime using the RegisterDecorator method of Simple Injector so our dev team does not need to go and update the composition root every time we add a decorator.
Here are some example classes/interfaces
public interface IValidator<T> where T : class
{
void Validate(T entity);
}
public class ClientValidator : IValidator<Client>
{
public void Validate(Client entity)
{
//Auto-generated
}
}
public class UserValidator : IValidator<User>
{
public void Validate(User entity)
{
//Auto-generated
}
}
public class ClientValidatorDecorator : IValidator<Client>
{
private readonly IValidator<Client> clientValidator;
public ClientValidatorDecorator(IValidator<Client> clientValidator)
{
this.clientValidator = clientValidator;
}
public void Validate(Client entity)
{
//New rules
this.clientValidator.Validate(entity);
}
}
public class UserValidatorDecorator : IValidator<User>
{
private readonly IValidator<User> userValidator;
public UserValidatorDecorator(IValidator<User> userValidator)
{
this.userValidator = userValidator;
}
public void Validate(User entity)
{
//New rules
this.userValidator.Validate(entity);
}
}
public class ValidationContext
{
private readonly IValidator<Client> client;
private readonly IValidator<User> user;
public ValidationContext(IValidator<Client> client, IValidator<User> user)
{
this.client = client;
this.user = user;
}
}
We I am trying to do something like so:
public void RegisterServices(Container container)
{
container.Register(typeof(IValidator<>), AssemblyManifest.GetAssemblies());
container.RegisterDecorator(typeof(IValidator<>), GetType, Lifestyle.Transient, UseType);
}
private static Type GetType(DecoratorPredicateContext ctx)
{
//Return appropriate Decorator
}
private static bool UseType(DecoratorPredicateContext ctx)
{
//Predicate
}
Unfortunately, unless I resolve a concrete type RegisterDecorator throws an error, so resolving another generic seems out. I am not sure how to proceed. Is there a way to do something like this? Is there a better way to get the intended functionality without decorators? We were thinking partial classes, but that has its own set of issues.
Any help will be appreciated!
Rather than plugging in decorators you could use a Composite Validator to enable the addition of IValidator<> implementations as required. This solution would allow the code to contain multiple IValidator<>'s for the same type.
Internally your code will still be able to depend on a single IValidator<T> which would resolve to the CompositeValidator that would call zero or more validators depending on what has been registered in the container at runtime.
The composite validator:
public class CompositeValidator<T> : IValidator<T>
{
public readonly IEnumerable<IValidator<T>> validators;
public CompositeValidator(IEnumerable<IValidator<T>> validators)
{
this.validators = validators;
}
public void Validate(T item)
{
foreach(var validator in this.validators)
{
validator.Validate(item);
}
}
}
The container is configured like this:
var assemblies = new[] { typeof(IValidator<>).Assembly };
var container = new Container();
container.RegisterCollection(typeof(IValidator<>), assemblies);
container.Register(typeof(IValidator<>), typeof(CompositeValidator<>));
where the assemblies variable contains all the assemblies you want to search for validators.
When you resolve IValidator<User> using container.GetInstance<IValidator<User>>() or through constructor injection you get back CompositeValidator<User> which internally references any and all IValidator<User>'s.
The way to get decorators of a type using batch registration is by calling the GetTypesToRegister method overload that accepts a TypesToRegisterOptions object. This way you can instruct SI to return decorators as well.
container.Register(typeof(IValidator<>), assemblies);
var t1 = container.GetTypesToRegister(typeof(IValidator<>), assemblies);
var t2 = container.GetTypesToRegister(typeof(IValidator<>), assemblies,
new TypesToRegisterOptions { IncludeDecorators = true });
foreach (Type t in t2.Except(t1)) {
container.RegisterDecorator(typeof(IValidator<>), t);
}
Do note that I do not suggest using this code. #qujck's answer addresses the design issue you have with your code, and his solutions therefore brings you to a much better place.

Register generic factory for all types which implements an interface

I have generic factory
public interface IViewModelFactory<T> where T : IViewModel
{
T Create<TU>(TU par);
}
public class ViewModelFactory<T> : IViewModelFactory<T> where T : IViewModel
{
private readonly ILifetimeScope _scope;
public ViewModelFactory(ILifetimeScope scope)
{
_scope = scope;
}
public T Create<TU>(TU par)
{
return _scope.Resolve<T>(new TypedParameter(typeof(TU), par));
}
}
which I can use for resolving viewmodel factory in my window class:
public WRPersons(IViewModelFactory<MRPersons> viewModelFactory)
{
var viewModel = viewModelFactory.Create(new MRPersonsUseCaseParams { Filter = 2 });
...
}
ViewModel is implemented by following code
public class MRPersons : IViewModel
{
public MRPersons(MRPersonsUseCaseParams par)
{
_filter = par.Filter;
}
}
public class MRPersonsUseCaseParams
{
public int Filter { get; set; }
}
Registration in my composition root looks like:
var builder = new ContainerBuilder();
builder.RegisterType<ViewModelFactory<MRPersons>>().As<IViewModelFactory<MRPersons>>();
builder.RegisterType<MRPersons>();
As you can see for each new ViewModel (now its only MRPerson) I will need to create two entries into my composition root. Thus for MRCar it will be:
builder.RegisterType<ViewModelFactory<MRCar>>().As<IViewModelFactory<MRCar>>();
builder.RegisterType<MRCar>();
I would like to automatize these registration somehow. I experimented with RegisterAssemblyTypes/AsClosedTypesOf but without success. Can somebody help me?
EDIT:
Based on answer codeline
builder.RegisterType<ViewModelFactory<MRPersons>>().As<IViewModelFactory<MRPersons>>();
is replaced by
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
Full automatic registration looks like:
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly()).Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass).AsSelf();
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
For better testable solution it would be fine to even replace MRPersons by IMRPersons:
public class MRPersons : IViewModel, IMRPersons
{
public MRPersons(MRPersonsUseCaseParams par)
{
_filter = par.Filter;
}
}
public class MRPersonsUseCaseParams
{
public int Filter { get; set; }
}
public interface IMRPersons
{
}
Thus registration in composition root would looks like (NEED TO BE CORRECTED)
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly()).Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass).As<??????>.AsSelf();
This would allows me to pass factory into constructor in following way:
public WRPersons(IViewModelFactory<IMRPersons> viewModelFactory)
{
var viewModel = viewModelFactory.Create(new MRPersonsUseCaseParams { Filter = 2 });
...
}
EDIT2:
During chat with Cyril Durand he provided solution for ViewModelFactory without reference to ILifetimeScope. Here is a code:
public interface IViewModelFactory2<T, TU> where T : IViewModel
{
T Create(TU par);
}
public class ViewModelFactory2<T, TU> : IViewModelFactory2<T, TU> where T : IViewModel
{
private readonly Func<TU, T> _factory;
public ViewModelFactory2(Func<TU, T> factory)
{
_factory = factory;
}
public T Create(TU par)
{
return _factory(par);
}
}
My original factory is Ok too since it is presented in composition root where strong references to DI container can be used.
You want to register ViewModelFactory<> as IViewModelFactory<>, you can do it using the RegisterGeneric method.
builder.RegisterGeneric(typeof(ViewModelFactory<>)).As(typeof(IViewModelFactory<>));
Then you will be able to resolve IViewModelFactory<MRCar> without any other registration.
See Registration Concepts - Open Generic Components for more information
For the second part of the question :
For better testable solution it would be fine to even replace MRPersons by IMRPersons
It is not so easy because there is no way to know which interface to use. You can use the AsImplementedInterfaces which will be equivalent to As<IMRPersons>().As<IViewModel>() but it may be a problem if you have a lot of implemented interface.
builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly())
.Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass)
.AsImplementedInterfaces();
Or you can use a convention that will register all X asIX but I'm not a big fan of this kind of registration.
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(x => iViewModelType.IsAssignableFrom(x) && x.IsClass)
.As(t => t.GetInterfaces().Where(i => i.Name.EndsWith(t.Name)));
By the way, after chatting, we figured out that you don't need a IViewModelFactory<> at all but you only need a dependency on Func<TParam, T>

DI and Lifetime Management

what is the 'best' way to manage the lifecycle of a disposable object when it is injected into another class. The example I keep running into is when running database queries using entity framework in a class that has a long lifetime.
Here is an example
public class CustomerViewModel
{
private ICustomerRepository _customerRepository;
public CustomerViewModel(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
public void AddCustomer(Customer customer)
{
_customerRepository.Customers.Add(customer);
_customerRepository.SaveChanges();
}
}
The code above looks perfectly innocent to me, however the _customerRepository object exists for as long as the CutomerViewModel exists for, which is much longer than it should.
If I were writting this code without DI i would do this:
public class CustomerViewModel
{
public void AddCustomer(Customer customer)
{
using (var customerRepository = new CustomerRepository())
{
customerRepository.Customers.Add(customer);
customerRepository.SaveChanges();
}
}
}
Which handles the lifecycle of CustomerRepository correctly.
How is this supposed to be managed when a class requires a Disposable object to have a shorter lifetime than itself?
The method I am using now is to create a RepositoryCreator object, which knows how to initialize a repository, but this feels wrong:
public class CustomerViewModel
{
private ICustomerRepositoryCreator _customerRepositoryCreator;
public CustomerViewModel(ICustomerRepositoryCreator customerRepositoryCreator)
{
_customerRepositoryCreator= customerRepositoryCreator;
}
public void AddCustomer(Customer customer)
{
using (var customerRepository = _customerRepositoryCreator.Create())
{
customerRepository.Customers.Add(customer);
customerRepository.SaveChanges();
}
}
}
UPDATE
So would doing something like this be preferable, it could be made generic but for the sake of this example I will not do this.
public class CustomerViewModel
{
private ICustomerRepository _customerRepository;
public CustomerViewModel(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
public void AddCustomer(Customer customer)
{
_customerRepository.Add(customer);
}
}
public class CustomerRepository : ICustomerRepository
{
private readonly DbContext _dbContext;
public CustomerRepository(DbContext dbContext)
{
_dbContext = dbContext;
}
public void Add(Customer customer)
{
_dbContext.Customers.Add(customer);
_dbContext.Customers.SaveChanges();
}
}
And have a proxy which manages lifetime
public class CustomerRepositoryLifetimeProxy : ICustomerRepository
{
private readonly _container;
public CustomerRepositoryLifetimeProxy(Container container)
{
_container = container;
}
public void Add(Customer customer)
{
using (Container.BeginScope()) //extension method
{
    ICustomerRepository cRepo = Container.Resolve<ICustomerRepository>();
cRepo.Add(customer);
} // releases the instance
}
}
If this is better, should the Proxy know about the DI container, or should it rely on a factory?
The problem here is that your AddCustomer method in your ViewModel does to much. The viewmodel should not be responsible of handling business logic, and the repositories consumer shouldn't know nothing about committing a unit of work and should not be able to add a customer to the list of customers.
So instead, refactor your ICustomerResository to the following:
public interface ICustomerRepository
{
void Add(Customer customer);
}
In this case, the Add method should be atomic and do the commit itself. This way the viewmodel can depend on that interface and in case the viewmodel outlives the customer repository, you can wrap the real repository with a proxy:
public class CustomerRepositoryProxy : ICustomerRepository
{
private readonly Func<ICustomerRepository> repositoryFactory;
public CustomerRepositoryProxy(Func<ICustomerRepository> repositoryFactory) {
this.repositoryFactory = repositoryFactory;
}
public void Add(Customer customer) {
var repository = this.repositoryFactory.Invoke();
repository.Add(customer);
}
}
Of course this will start to become quite cumbersome if you have dozens of those IXXXRepository interfaces. In that case, you might want to migrate to one generic interface instead:
public interface IRepository<TEntity>
{
void Add(TEntity entity);
}
This way you can have one single proxy for all repositories:
public class RepositoryProxy<TEntity> : IRepository<TEntity>
{
private readonly Func<IRepository<TEntity>> repositoryFactory;
public CustomerRepositoryProxy(Func<IRepository<TEntity>> repositoryFactory) {
this.repositoryFactory = repositoryFactory;
}
public void Add(TEntity entity) {
var repository = this.repositoryFactory.Invoke();
repository.Add(entity);
}
}
In that case (assuming you wire your object graphs by hand) you can build up the viewmodel as follows:
new CustomerViewModel(
new RepositoryProxy<Customer>(
() => new CustomerRepository(unitOfWork)));
You can even take it one step further and implement the command/handler pattern and query/handler pattern. In that case you don't inject a IRepository<Customer> into your view model, but you inject an ICommandHandler<AddCustomer> into the view model and instead of injecting the AddCustomerCommandHandler implementation into the view model, you inject a proxy that creates the real handler when needed:
public class LifetimeScopedCommandHandlerProxy<TCommand> : ICommandHandler<TCommand>
{
private readonly Func<ICommandHandler<TCommand>> decorateeFactory;
public LifetimeScopedCommandHandlerProxy(
Func<ICommandHandler<TCommand>> decorateeFactory) {
this.decorateeFactory = decorateeFactory;
}
public void Handle(TCommand command) {
var decoratee = this.decorateeFactory.Invoke();
decoratee.Handle(command);
}
}
The view model will look as follows:
public class CustomerViewModel
{
private ICommandHandler<AddCustomer> addCustomerCommandHandler;
public CustomerViewModel(ICommandHandler<AddCustomer> addCustomerCommandHandler) {
this.addCustomerCommandHandler = addCustomerCommandHandler;
}
public void AddCustomer(Customer customer)
{
this.addCustomerCommandHandler.Handle(new AddCustomer(customer));
}
}
And the object graph will look similar as before:
new CustomerViewModel(
new LifetimeScopedCommandHandlerProxy<AddCustomer>(
() => new AddCustomerCommandHandler(unitOfWork)));
Of course, it will be much easier building these object graphs when using a container.
UPDATE
If you use a DI container, and you're not running in something like a web request, you will have to start a new 'scope' or 'request' explictly to inform the container what to do. With Simple Injector your proxy will looks like this:
public class LifetimeScopedCommandHandlerProxy<TCommand> : ICommandHandler<TCommand>
{
private readonly Container container;
private readonly Func<ICommandHandler<TCommand>> decorateeFactory;
// Here we inject the container as well.
public LifetimeScopedCommandHandlerProxy(Container container,
Func<ICommandHandler<TCommand>> decorateeFactory)
{
this.container = container;
this.decorateeFactory = decorateeFactory;
}
public void Handle(TCommand command) {
// Here we begin a new 'lifetime scope' before calling invoke.
using (container.BeginLifetimeScope())
{
var decoratee = this.decorateeFactory.Invoke();
decoratee.Handle(command);
}
// When the lifetime scope is disposed (which is what the using
// statement does) the container will make sure that any scope
// instances are disposed.
}
}
In that case your configuration might look like this:
// This instance lives as long as its scope and will be disposed by the container.
container.RegisterLifetimeScope<IUnitOfWork, DisposableUnitOfWork>();
// Register the command handler
container.Register<ICommandHandler<AddCustomer>, AddCustomerCommandHandler>();
// register the proxy that adds the scoping behavior
container.RegisterSingleDecorator(
typeof(ICommandHandler<>),
typeof(LifetimeScopedCommandHandlerProxy<>));
container.Register<CustomerViewModel>();
In general it is up to the creator to dispose a disposable object as soon es it is done with its usage. If your injected object can live through entire application lifecycle, i.e. without needing to dispose it in the meantime, than the normal DI approach (your first code block) is a good way to go. However, if you need to dispose the object as soon as possible, than a factory approach makes much more sense (last code block).

C# Interfaces implementation

I don't know how manage properly the interfaces in C#. My goal is to have an abstract class for my Business Layer Services that have some common methods (like Save(), Dispose()), that call different DAL repository methods. I wish to avoid to repeat in all my services something like:
public Save()
{
repository.Save();
}
I have a scenario similar to that:
Interface
namespace Common
{
public interface IRepository
{
void Save;
void Dispose;
}
}
DAL
namespace DAL
{
public Repository : IRepository
{
public void Save() {};
public void Dispose() {};
public void Add() {}
}
}
BL
namespace BL
{
public abstrac BaseService
{
protected IRepository repository;
protected BaseService(IRepository repo)
{
repository = repo;
}
public Save()
{
repository.Save();
}
}
//...
//Tentative 1
public Service : BaseService
{
private Repository rep;
public Service()
: base(new DAL.Repository())
{
rep = base.repository; // ERROR: cannot convert IRepository to Repository
}
}
}
I tried also this:
//Tentative 2
public Service : BaseService
{
private IRepository rep;
public Service()
: base(new DAL.Repository())
{
rep = base.repository; // OK
}
public void Add()
{
rep.Add() // ERROR: IRepository doesn't contain a definition for 'Add'
}
}
I know I could define in the interface all the methods I want to use, but I'll will have to manage a lot of problems with generic types and, as you should have understand from my question, I'm quite new in C# and I wish to avoid complexity is is possible, utill I'll be more expert at least :)
Firstly I think you're having a name clash with you member
IRepository rep.
Try using
DAL.IRepository rep
The reason that you're getting an error is that you've defined "Add" as something unique to "Repository". Your member variable is an "IRepository" allowing you to put anything that implements "IRepository" onto it.
Just because you CAN put a Repository into it, doesn't mean that everything on it is going to be a repository. (Think of it look good 'ol fingers and thumbs, all thumbs are fingers, but not all fingers are thumbs)
If you NEED to call add on any repository, then add it to the interface. Else, you need to decide whether or not that member should be IRepository or Repository.
Alternatively, you COULD use
Repository myRep = rep as Repository;
if(rep!=null)
{
myRep.Add();
...
profit();
}
public Service()
: base(new DAL.Repository())
{
rep = (Repository)base.repository;
}
This way u will get the Add() service which is not a part of IRepository but a newer implementation in the extended class.
Seeing as your main problem is the lack of accessibility to the Add method, and seeing as this is a relative common method anyway, I would firstly recommend adding it to your IRepository, so it looks like this:
public interface IRepository
{
void Add();
void Save();
void Dispose();
}
You would then implement your appropriate repositories whilst inheriting from IRepository. Now, understandably you may want to be able to access custom methods on a Repository. In order to resolve this what you could do is have your BaseService accept a generic repository:
public BaseService<T> where T : IRepository
{
protected T repository { get; set; }
protected BaseService(T repo)
{
repository = repo;
}
}
Then a service would look like this
public UserService : BaseService<UserRepository>
{
public UserService() : base(new DAL.UserRepository())
{
// base.Repository is now a UserRepository.
}
}
With this implementation your UserService will be able to access all of the methods that UserRepository exposes, as it's strongly typed with the generic. Hope this helps.

Categories