Assume I have 2 entities Foo and Bar as follows:
public class Foo
{
public int FooID {get;set;}
public string FooName {get;set;}
}
public class Bar
{
public int BarID {get;set;}
public string BarName {get;set;}
public int FooID {get;set;}
}
For each entity will have its repository:
public class FooRepository
{
public IEnumerable<Foo> getFoo()
{
//do something
}
}
public class BarRepository
{
public IEnumerable<Bar> getBar()
{
//do something
}
public IEnumerable<Bar> getBar(int FooID)
{
//get bar base on foo id
}
}
Each of those repositories will have an associated service:
public class FooService
{
//depend on Foo repository
}
public class BarService
{
//depend on Bar repository
}
Now I want to make a function to see if a Foo is in used in Bar. I thought of 2 methods to implement this function:
Method 1:
public class BarService
{
private BarRepository repository = new BarRepository();
public bool isFooExisted(int FooID)
{
var bars = this.repository.getBar(FooID);
return bars.Count > 0;
}
}
Somehow, this is look like it is violating Single Responsible Principle since BarService is used to check for a Foo. So I came up with method 2:
Method 2:
public class BarService
{
private BarRepository repository = new BarRepository();
public IEnumerable<Bar> getBar(int FooID)
{
return this.repository.getBar(FooID);
}
}
public class FooService
{
private BarService service = new BarService();
public bool isFooExisted(int FooID)
{
var bars = service.getBar(FooID);
return bars.Count > 0;
}
}
I wonder is it a good idea for services depend on each other like this. Please suggest me which one of those method above is good to follow or any other method will help
I personally would avoid services using other services because sooner or later you'll get a circular reference. Having the services not depend on each other also makes for looser coupling and ease of testability. So i would go for method 1.
The problem with this approach comes when you want to reuse functionality between services. In your case you can just defer calls to the respective repository, but in more complex cases you may need to add a domain object that contain common business logic that can be re-used in the different services. For example, if you had to have a complex isFooExisted method in both services, you might do something like this (note that I have changed your code to use dependency injection to make your code more testable):
public class BarService
{
private FooEntity fooEntity;
public BarService(IFooRepository repository)
{
this.fooEntity = new FooEntity(repository);
}
public IEnumerable<Foo> getFoo(int FooID)
{
return fooEntity.getFoo(FooID);
}
}
public class FooService
{
private FooEntity fooEntity;
public FooService(IFooRepository repository)
{
this.fooEntity = new FooEntity(repository);
}
public IEnumerable<Foo> getFoo(int FooID)
{
return fooEntity.getFoo(FooID);
}
}
public class FooEntity
{
private IFooRepository repository;
public FooEntity(IFooRepository repository)
{
this.repository = repository;
}
public bool isFooExisted(int FooID)
{
/** Complex business logix **/
}
}
And for the simple case I'd just use the same repository directly and not have the domain object:
public class BarService
{
private IFooRepository repository;
public BarService(IFooRepository repository)
{
this.repository = repository;
}
...
}
public class FooService
{
private IFooRepository repository;
public FooService(IFooRepository repository)
{
this.repository = repository;
}
...
}
Hope this helps.
Related
I working on Dependency injection and taking following example if I need to use Customer class object reference in service that is implementation IService class which is best way to do so, considering customer object always going to be use in service class, or and abstract class here
public class Customer
{
public int ID {get; set;}
public string Name {get; set}
public string dosomething(){}
}
public interface IService
{
customer Serve(Guid RecordId);
}
public class Service : IService
{
public void Serve()
{
Console.WriteLine("Need to create Customer Object here");
Customer obj1 = new Customer();
obj1.ID = 2;
obj1.Name = "xyz";
}
}
public class Client
{
private IService _service;
public Client(IService service)
{
this._service = service;
}
}
Keep your model a "dumb" data container (DTO) that will never need dependencies (or for that matter, an abstraction).
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
}
Rather than having Customer do something, we have a service to do something with Customer.
public interface ISomething
{
string DoSomething(Customer customer);
}
public class Something : ISomething
{
public string DoSomething(Customer customer)
{
// Use customer to do something
return "done";
}
}
Then Service can accept ISomething as an injected dependency and process the Customer accordingly.
public interface IService
{
Customer Serve(Guid RecordId);
}
public class Service : IService
{
private readonly ISomething something;
public Service(ISomething something)
{
if (something == null)
throw new ArgumentNullException(nameof(something));
this.something = something;
}
public Customer Serve(Guid RecordId)
{
// No need to inject dependencies here
Customer obj1 = new Customer();
obj1.ID = 2;
obj1.Name = "xyz";
something.DoSomething(obj1);
return obj1;
}
}
The DTO's or the data transfer objects should contain only properties. There should not be any method implementation or an abstract method declaration or anything.
There can be a constructor in the DTO to initialize the members of the object. Try to have a look at the SOLID principles once.
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.
This question already has answers here:
How to avoid Dependency Injection constructor madness?
(10 answers)
Closed 7 years ago.
I currently have an ASP.Net MVC 5 app that uses 3 external datasources (calls are made to external APIs, responses are deserialized, and mapped to business POCOs).
The app currently uses SimpleInjector to inject concrete repositories for each datasource into a business logic layer for consumption.
The problem is, as more datasources are added (potentially 20-30), the constructor will be huge and injecting all these repositories seems cumbersome.
Is there a better pattern/approach to consuming all the datasources rather than using different repositories?
Would a facade or some other pattern be more appropriate?
Very generic examples:
public class MyObject(){
public IEnumerable<Cat> Cats { get; set; }
public IEnumerable<Dog> Dogs { get; set; }
public IEnumerable<Fish> Fish { get; set; }
}
public class BusinessLogic{
private readonly ISourceARepository _sourceA;
private readonly ISourceBRepository _sourceB;
private readonly ISourceCRepository _sourceC;
public BusinessLogic(ISourceARepository sourceA, ISourceBRepository sourceB, ISourceCRepository sourceC){
_sourceA = sourceA;
_sourceB = sourceB;
_sourceC = sourceC;
}
private Dog MapSourceARecordToDog(SourceARecord record){
var result = new Dog();
if(record != null){
result.Name = record.NameField;
result.Age = record.Age;
}
return result;
}
private Cat MapSourceBRecordToCat(SourceBRecord record){
var result = new Cat();
if(record != null){
result.Name = record.NameField;
result.Weight = record.WeightField;
}
return result;
}
private Fish MapSourceCRecordToFish(SourceCRecord record){
var result = new Fish();
if(record != null){
result.ID = record.IDField;
result.Name = record.NameField;
}
return result;
}
public MyObject GetResults(){
var result = new MyObject();
result.Dogs = _sourceA.GetAll().Select(MapSourceARecordToDog).ToList();
result.Cats = _sourceB.GetAll().Select(MapSourceBRecordToCat).ToList();
result.Fish = _sourceC.GetAll().Select(MapSourceCRecordToFish).ToList();
return result;
}
}
public class SourceARespository : ISourceARepository{
public IEnumerable<SourceAResult> GetAll(){
return new List<SourceAResult>();
}
}
public class SourceBRespository : ISourceBRepository{
public IEnumerable<SourceBResult> GetAll(){
return new List<SourceBResult>();
}
}
public class SourceCRespository : ISourceCRepository{
public IEnumerable<SourceCResult> GetAll(){
return new List<SourceCResult>();
}
}
Update:
This is not a duplicate of the constructor madness question, because in this scenario, a class needs many different datasources, but still has single responsibility. Hence, it warrants its own explanation and answer.
You should only be injecting one repository per entity into a consumer that depends on it. You may also choose to adapt the repository with a business class intermediary.
UPDATE:
Based on the information provided in the question and the problem statement, here is one possible solution. Define your core infrastructure like this:
public abstract class Entity<TEntity, TDomainObject, TIRepository>
where TEntity : Entity<TEntity, TDomainObject, TIRepository>
where TDomainObject : Entity<TEntity, TDomainObject, TIRepository>.BaseDomainObject, new()
where TIRepository : Entity<TEntity, TDomainObject, TIRepository>.IBaseRepository
{
public class BaseDomainObject {}
public interface IBaseRepository
{
IEnumerable<TDomainObject> GetAll();
IEnumerable<T> GetAllMapped<T>(Func<TDomainObject, T> mapper);
}
public class BaseRepository : IBaseRepository
{
public IEnumerable<TDomainObject> GetAll()
{
return new List<TDomainObject>();
}
public IEnumerable<T> GetAllMapped<T>(Func<TDomainObject, T> mapper)
{
return this.GetAll().Select(mapper);
}
}
}
Define your source entities like this:
public class SourceA : Entity<SourceA, SourceA.DomainObject, SourceA.IRepository>
{
public class DomainObject : BaseDomainObject
{
public string Name;
public int Age;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository, IRepository {}
}
public class SourceB : Entity<SourceB, SourceB.DomainObject, SourceB.IRepository>
{
public class DomainObject : BaseDomainObject
{
public string Name;
public decimal Weight;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository, IRepository {}
}
public class SourceC : Entity<SourceC, SourceC.DomainObject, SourceC.IRepository>
{
public class DomainObject : BaseDomainObject
{
public Guid Id;
public string Name;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository, IRepository {}
}
Then define an ISourceRepositoryContext interface like this and add each source repository interface here:
public interface ISourceRepositoryContext
{
SourceA.IRepository SourceARepository { get; }
SourceB.IRepository SourceBRepository { get; }
SourceC.IRepository SourceCRepository { get; }
}
Then define a default implementation for the interface:
public class DefaultSourceRepositoryContext : ISourceRepositoryContext
{
public SourceA.IRepository SourceARepository => new SourceA.Repository();
public SourceB.IRepository SourceBRepository => new SourceB.Repository();
public SourceC.IRepository SourceCRepository => new SourceC.Repository();
}
Define your result transport objects:
public class Dog
{
public string Name;
public int Age;
}
public class Cat
{
public string Name;
public decimal Weight;
}
public class Fish
{
public Guid Id;
public string Name;
}
public class MyObject
{
public IEnumerable<Cat> Cats { get; set; }
public IEnumerable<Dog> Dogs { get; set; }
public IEnumerable<Fish> Fish { get; set; }
}
Then consume the ISourceRepositoryContext in your BusinessLogic class:
public class BusinessLogic
{
protected ISourceRepositoryContext repositories;
public BusinessLogic(ISourceRepositoryContext repositories)
{
this.repositories = repositories;
}
public MyObject GetResults(string param1)
{
return new MyObject()
{
Dogs = this.repositories.SourceARepository.GetAllMapped
(domainObject=>new Dog
{
Age = domainObject.Age,
Name = domainObject.Name
}),
Cats = this.repositories.SourceBRepository.GetAllMapped
(domainObject=>new Cat
{
Name = domainObject.Name,
Weight = domainObject.Weight
}),
Fish = this.repositories.SourceCRepository.GetAllMapped
(domainObject=>new Fish
{
Id = domainObject.Id,
Name = domainObject.Name
}),
};
}
}
I've confirmed that the above compiles under C# 6.0.
I would recommend changing IRepository to IBusiness in Entity and split out the data access concerns from into an IDataAccess interface that only the IBusiness implementors receive via their constructors. And then change the ISourceRepositoryContext to ISourceEntities and change the IRepository properties in that interface to IBusiness properties instead.
The BusinessLogic class is the part that really concerns me. Are you sure this one class won't be taking on too many concerns? Is this supposed to be a UoW class?
For a more complete solution based on similar techniques, check out my answer to this other question: .NET Managing Layers Relationships
Given the code below, How do I set up the registrations in Castle Windsor (latest version) to make ISomeService resolve to SomeDecorator< SomeRequest, SomeResponse>?
public interface IService<in TRequest, out TResponse>
{
TResponse Get(TRequest request);
}
public class SomeRequest
{
public int SomeId { get; set; }
public int SomeOtherId { get; set; }
}
public class SomeResponse
{
public int SomeId { get; set; }
public string SomeName { get; set; }
public IEnumerable<string> SomeList { get; set; }
}
public interface ISomeService : IService<SomeRequest, SomeResponse> { }
public class SomeService : ISomeService
{
public SomeResponse Get(SomeRequest request)
{
return new SomeResponse { SomeId = request.SomeId, SomeName = "The Name", SomeList = new List<string>() };
}
}
public class SomeDecorator<TRequest, TResponse> : IService<TRequest, TResponse>
{
private readonly IService<TRequest, TResponse> _service;
public SomeDecorator(IService<TRequest, TResponse> service)
{
_service = service;
}
public TResponse Get(TRequest request)
{
//Do something before
var response = _service.Get(request);
//Do something after
return response;
}
}
With the following registrations, ISomeService is resolving to SomeService, not SomeDecorator
< SomeRequest, SomeResponse>
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component
.For(IService<SomeRequest,SomeResponse>)
.ImplementedBy(ISomeService));
container.Register(Component
.For(ISomeService)
.ImplementedBy(SomeService));
container.Register(Component
.For(IService<,>)
.ImplementedBy(SomeDecorator<,>)
.IsDefault());
}
When I try to register ISomeService to be implemented by SomeDecorator< SomeRequest, SomeResponse>, I get the following error message:
Unable to cast object of type 'SomeDecorator`2[SomeRequest,SomeResponse]' to type 'ISomeService'.
Here's one way to get it working. The downside of this solution is that you have to register the decorator against each class you want to decorate.
As I said in my comment above you can simplify your design by getting rid of ISomeService and go with public class SomeService : IService<SomeRequest, SomeResponse> instead. The registration for the decorator then looks like this:
container.Register(
Component.For<IService<SomeRequest, SomeResponse>>()
.ImplementedBy<SomeDecorator<SomeRequest, SomeResponse>>(),
Component.For<IService<SomeRequest, SomeResponse>>()
.ImplementedBy<SomeService>());
Also note you could automate the registration of all your generic implementations with LINQ queries.