I have a hard time wrapping my head around the difference between thees 2 way of using the IlogService, or maybe I am wrong and there is only one that is correct if I want to use dependency injection?
This way in class that use ILogService....
private static readonly ILogService _log = new LogService();
Or this way in class that use ILogService...
private readonly ILogService _logger;
public MyClassThatUseIlogerService(ILogService logger)
{
_logger = logger;
}
Interface
public interface ILogService
{
void Add(string val);
}
public class LogService :ILogService
{
public void Add(string val)
{
Console.WriteLine(val;
}
}
Related
I have an ASP.NET Core app with various controllers that inherit from BaseController. I need to implement some basic benchmarking tests, using Stopwatch, it will just start at the beginning of an action method and finish at the end. I can turn this on and off via appsettings.json. There is an ILogger factory in Startup.cs:
public void Configure ( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory ) {
loggerFactory.AddConsole( Configuration.GetSection( "Logging" ) );
loggerFactory.AddDebug();
loggerFactory.AddFile(#"C:\Logs\Portal\portal-{Date}.txt");
I have added ILogger to my BaseController (below), I am hoping this will be supplied via DI. Given the above, can I use this to log my benchmark results to file in a different location to the startup file? I would like a .csv file with certain columns which i can populate with results. Is this possible?
public class BaseController : Controller {
protected AppSettings AppSettings;
protected IMapper Mapper;
protected IPortalApiService PortalApiService;
protected ILogger Logger;
protected UserManager<ApplicationUser> UserManager;
private static Stopwatch _stopWatch = new Stopwatch();
private static long _seconds;
public BaseController ( IMapper mapper,
IOptions<AppSettings> appSettings,
UserManager<ApplicationUser> userManager,
IPortalApiService PortalApiService,
ILogger logger) {
Mapper = mapper;
AppSettings = appSettings.Value;
UserManager = userManager;
PortalApiService = PortalApiService;
Logger = logger;
}
public BaseController ( IMapper mapper,
IOptions<AppSettings> appSettings,
UserManager<ApplicationUser> userManager,
ILogger logger) {
Mapper = mapper;
AppSettings = appSettings.Value;
UserManager = userManager;
Logger = logger;
}
protected Task<ApplicationUser> GetCurrentUserAsync () {
return UserManager.GetUserAsync( HttpContext.User );
}
public void StartBenchmark()
{
if (AppSettings.EnableBenchmarkLogging)
{
_stopWatch = Stopwatch.StartNew();
}
}
public void EndBenchmark()
{
if (_stopWatch.IsRunning)
{
_stopWatch.Stop();
_seconds = _stopWatch.ElapsedMilliseconds;
//logging to do
}
}
}
It is not a good idea to use a BaseController in MVC. There are better ways to implement crosscutting concerns. In this particular case, you could use a global filter.
public class BenchmarkFilter : IActionFilter
{
private readonly ILogger Logger;
// DON'T DECLARE STATIC!!
private Stopwatch _stopWatch = new Stopwatch();
public BenchmarkFilter(ILogger logger)
{
_logger = logger ??
throw new ArgumentNullException(nameof(logger));
}
public void OnActionExecuting(ActionExecutingContext context)
{
_stopWatch = Stopwatch.StartNew();
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (_stopWatch.IsRunning)
{
_stopWatch.Stop();
var seconds = _stopWatch.ElapsedMilliseconds;
//logging to do
}
}
}
This allows you to inject services via DI through the constructor without having to add those parameters to every controller that subclasses a common BaseController, separating the concern of benchmarking from the controller entirely.
Usage
In Startup.cs, add the filter in the ConfigureServices method.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(typeof(BenchmarkFilter)); // runs on every action method call
});
services.AddScoped<BenchmarkFilter>();
// ....
}
I have looked around on StackOverflow for a solution to my problem. Though I don't think this is a unique problem, I haven't been able to find a good solution.
In my WPF application, in my viewmodels, I need to call some services to return some data. These services get injected with UnitOfWork which in turn gets injected with the DbContext. This dbcontext that get injected into the UnitOfWork should differ based on some criteria.
I am having trouble doing the IoC container registrations the right way and injecting the right DbContext at runtime. So, if someone can please fill in the blanks (in the unity registrations as well as it's usage). I have some inline comments in the following code where I am in trouble and need help. Thanks.
If someone can replace my Registration code the right way and also educate me how to use it in my WPF ViewModel class, that would be truly great! Thanks.
One final note: If you find coding errors in this code, please don't start wondering how does this even compile? The code here is not my real code. To simplify things, I just wrote them up. But it does resemble very closely to my real app code.
public interface IDBContext{}
public interface IUnitOfWork{}
public interface ISomeEntityService{}
public interface IRepository<T> where T : class
{ T GetSingle( Expression<Func<T, bool>> predicate ); }
public class DBContext1 : IDBContext
{
public DBContext1(connString) : base(connString){}
}
public class DBContext2 : IDBContext
{
public DBContext2(connString) : base(connString){}
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDBContext context;
private readonly IDbSet<T> dbSet;
public Repository(IDBContext ctx)
{
context = ctx;
dbSet = ((DbContext)context).Set<T>();
}
public T GetSingle( Expression<Func<T, bool>> predicate )
{
return ((DbContext)context).Set<T>().SingleOrDefault(predicate);
}
}
public class UnitOfWork : IUnitOfWork
{
IDBContext ctx;
private Dictionary<string, dynamic> repositories;
public UnitOfWork(IDBContext context)
{
ctx = context;
}
public IRepository<T> Repository<T>() where T : class
{
if (repositories == null)
repositories = new Dictionary<string, dynamic>();
var type = nameof(T);
if (repositories.ContainsKey(type))
return (IRepository<T>)repositories[type];
var repositoryType = typeof(Repository<>);
repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof(T)), ctx));
return repositories[type];
}
public int SaveChanges()
{
return ctx.SaveChanges();
}
}
public class MyUnityBootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
Container.RegisterType<IDBContext, DBContext1>("Context1");
Container.RegisterType<IDBContext, DBContext2>("Context2");
Container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
Container.RegisterType<IUnitOfWork, UnitOfWork>();
}
}
public class SomeEntityService : ISomeEntityService
{
private IUnitOfWork uow;
public ConsumerService( IUnitOfWork _uow )
{ uow = _uow; }
public SomeEntity GetSomeData( int id )
{
return uow.Repository<SomeEntity>().GetSingle( x => x.Id == id);
}
}
public class SomeViewModel : BindableBase
{
private readonly ISomeEntityService someService;
public SomeViewModel( ISomeEntityService _someService)
{
// when I call someService, I want to make sure it is using either
// DBContext1 or DBContext2 based on some condition I can set here.
// This is where I am totally stuck.
someService = _someService;
}
// get the repository instance with an id of 1000
someService.GetSomeData( 1000 );
}
/*
I could do something like this. But I am afraid, I am violating
two of the best practices recommendations.
1. I am creating a dependency to my IoC Container here.
2. I am using the container as a Service Locator
*/
public class SomeViewModel : BindableBase
{
private readonly ISomeEntityService someService;
public SomeViewModel()
{
var container = SomeHowGetTheContainer();
/*
1. Call Container.Resolve<IDBContext>(with the required context);
2. Use the retrieved context to inject into the UnitOfWork
3. Use the retrieved UnitOfWork to inject into the service
But that would be like throwing everything about best practices to the wind!
*/
someService = container.Resolve<ISomeEntityService>( /*do some magic here to get the right context*/)
}
// get the repository instance with an id of 1000
someService.GetSomeData( 1000 );
}
Add a factory like this that resolves your ISomeEntityService:
public MySomeEntityServiceFactory
{
public MySomeEntityServiceFactory( IUnityContainer container )
{
_container = container;
}
public ISomeEntityService CreateSomeEntityService( bool condition )
{
return _container.Resolve<ISomeEntityService>( condition ? "VariantA" : "VariantB" );
}
private readonly IUnityContainer _container;
}
and add two named bindings like:
_container.RegisterType<ISomeEntityService, SomeEntityService>( "VariantA", new InjectionConstructor( new ResolvedParameter<IDBContext>( "VariantA" ) ) );
_container.RegisterType<ISomeEntityService, SomeEntityService>( "VariantB", new InjectionConstructor( new ResolvedParameter<IDBContext>( "VariantB" ) ) );
For IUnitOfWork, you can add a similar factory that resolves the unit of work, and call it in SomeEntityService's constructor passing in the IDBContext...
Those factories are additional dependencies themselves, btw...
I'm trying to implement IoC in my windows form application. My choice fell on Simple Injector, because it's fast and lightweight. I also implement unit of work and repository pattern in my apps. Here is the structure:
DbContext:
public class MemberContext : DbContext
{
public MemberContext()
: base("Name=MemberContext")
{ }
public DbSet<Member> Members { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();\
}
}
Model:
public class Member
{
public int MemberID { get; set; }
public string Name { get; set; }
}
GenericRepository:
public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
where TEntity : class
{
internal DbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
}
MemberRepository:
public class MemberRepository : GenericRepository<Member>, IMemberRepository
{
public MemberRepository(DbContext context)
: base(context)
{ }
}
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
public DbContext context;
public UnitOfWork(DbContext context)
{
this.context = context;
}
public void SaveChanges()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
MemberService:
public class MemberService : IMemberService
{
private readonly IUnitOfWork unitOfWork;
private readonly IMemberRepository memberRepository;
public MemberService(IUnitOfWork unitOfWork, IMemberRepository memberRepository)
{
this.unitOfWork = unitOfWork;
this.memberRepository = memberRepository;
}
public void Save(Member member)
{
Save(new List<Member> { member });
}
public void Save(List<Member> members)
{
members.ForEach(m =>
{
if (m.MemberID == default(int))
{
memberRepository.Insert(m);
}
});
unitOfWork.SaveChanges();
}
}
In Member Form I only add a textbox to input member name and a button to save to database. This is the code in member form:
frmMember:
public partial class frmMember : Form
{
private readonly IMemberService memberService;
public frmMember(IMemberService memberService)
{
InitializeComponent();
this.memberService = memberService;
}
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
memberService.Save(member);
}
}
I implement the SimpleInjector (refer to http://simpleinjector.readthedocs.org/en/latest/windowsformsintegration.html) in Program.cs as seen in the code below:
static class Program
{
private static Container container;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(new frmMember((MemberService)container.GetInstance(typeof(IMemberService))));
}
private static void Bootstrap()
{
container = new Container();
container.RegisterSingle<IMemberRepository, MemberRepository>();
container.Register<IMemberService, MemberService>();
container.Register<DbContext, MemberContext>();
container.Register<IUnitOfWork, UnitOfWork>();
container.Verify();
}
}
When I run the program and add a member, it doesn't save to database. If I changed container.Register to container.RegisterSingle, it will save to database. From the documentation, RegisterSingle will make my class to be a Singleton. I can't using RegisterLifeTimeScope because it will generate an error
"The registered delegate for type IMemberService threw an exception. The IUnitOfWork is registered as 'Lifetime Scope' lifestyle, but the instance is requested outside the context of a Lifetime Scope"
1) How to use SimpleInjector in Windows Form with UnitOfWork & Repository pattern?
2) Do I implement the patterns correctly?
The problem you have is the difference in lifestyles between your service, repository, unitofwork and dbcontext.
Because the MemberRepository has a Singleton lifestyle, Simple Injector will create one instance which will be reused for the duration of the application, which could be days, even weeks or months with a WinForms application. The direct consequence from registering the MemberRepository as Singleton is that all dependencies of this class will become Singletons as well, no matter what lifestyle is used in the registration. This is a common problem called Captive Dependency.
As a side note: The diagnostic services of Simple Injector are able to spot this configuration mistake and will show/throw a Potential Lifestyle Mismatch warning.
So the MemberRepository is Singleton and has one and the same DbContext throughout the application lifetime. But the UnitOfWork, which has a dependency also on DbContext will receive a different instance of the DbContext, because the registration for DbContext is Transient. This context will, in your example, never save the newly created Member because this DbContext does not have any newly created Member, the member is created in a different DbContext.
When you change the registration of DbContext to RegisterSingleton it will start working, because now every service, class or whatever depending on DbContext will get the same instance.
But this is certainly not the solution because having one DbContext for the lifetime of the application will get you into trouble, as you probably already know. This is explained in great detail in this post.
The solution you need is using a Scoped instance of the DbContext, which you already tried. You are missing some information on how to use the lifetime scope feature of Simple Injector (and most of the other containers out there). When using a Scoped lifestyle there must be an active scope as the exception message clearly states. Starting a lifetime scope is pretty simple:
using (ThreadScopedLifestyle.BeginScope(container))
{
// all instances resolved within this scope
// with a ThreadScopedLifestyleLifestyle
// will be the same instance
}
You can read in detail here.
Changing the registrations to:
var container = new Container();
container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();
container.Register<IMemberRepository, MemberRepository>(Lifestyle.Scoped);
container.Register<IMemberService, MemberService>(Lifestyle.Scoped);
container.Register<DbContext, MemberContext>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
and changing the code from btnSaveClick() to:
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
using (ThreadScopedLifestyle.BeginScope(container))
{
var memberService = container.GetInstance<IMemberService>();
memberService.Save(member);
}
}
is basically what you need.
But we have now introduced a new problem. We are now using the Service Locator anti pattern to get a Scoped instance of the IMemberService implementation. Therefore we need some infrastructural object which will handle this for us as a Cross-Cutting Concern in the application. A Decorator is a perfect way to implement this. See also here. This will look like:
public class ThreadScopedMemberServiceDecorator : IMemberService
{
private readonly Func<IMemberService> decorateeFactory;
private readonly Container container;
public ThreadScopedMemberServiceDecorator(Func<IMemberService> decorateeFactory,
Container container)
{
this.decorateeFactory = decorateeFactory;
this.container = container;
}
public void Save(List<Member> members)
{
using (ThreadScopedLifestyle.BeginScope(container))
{
IMemberService service = this.decorateeFactory.Invoke();
service.Save(members);
}
}
}
You now register this as a (Singleton) Decorator in the Simple Injector Container like this:
container.RegisterDecorator(
typeof(IMemberService),
typeof(ThreadScopedMemberServiceDecorator),
Lifestyle.Singleton);
The container will provide a class which depends on IMemberService with this ThreadScopedMemberServiceDecorator. In this the container will inject a Func<IMemberService> which, when invoked, will return an instance from the container using the configured lifestyle.
Adding this Decorator (and its registration) and changing the lifestyles will fix the issue from your example.
I expect however that your application will in the end have an IMemberService, IUserService, ICustomerService, etc... So you need a decorator for each and every IXXXService, not very DRY if you ask me. If all services will implement Save(List<T> items) you could consider creating an open generic interface:
public interface IService<T>
{
void Save(List<T> items);
}
public class MemberService : IService<Member>
{
// same code as before
}
You register all implementations in one line using Batch-Registration:
container.Register(typeof(IService<>),
new[] { Assembly.GetExecutingAssembly() },
Lifestyle.Scoped);
And you can wrap all these instances into a single open generic implementation of the above mentioned ThreadScopedServiceDecorator.
It would IMO even be better to use the command / handler pattern (you should really read the link!) for this type of work. In very short: In this pattern every use case is translated to a message object (a command) which is handled by a single command handler, which can be decorated by e.g. a SaveChangesCommandHandlerDecorator and a ThreadScopedCommandHandlerDecorator and LoggingDecorator and so on.
Your example would then look like:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
public class CreateMemberCommand
{
public string MemberName { get; set; }
}
With the following handlers:
public class CreateMemberCommandHandler : ICommandHandler<CreateMemberCommand>
{
//notice that the need for MemberRepository is zero IMO
private readonly IGenericRepository<Member> memberRepository;
public CreateMemberCommandHandler(IGenericRepository<Member> memberRepository)
{
this.memberRepository = memberRepository;
}
public void Handle(CreateMemberCommand command)
{
var member = new Member { Name = command.MemberName };
this.memberRepository.Insert(member);
}
}
public class SaveChangesCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratee;
private DbContext db;
public SaveChangesCommandHandlerDecorator(
ICommandHandler<TCommand> decoratee, DbContext db)
{
this.decoratee = decoratee;
this.db = db;
}
public void Handle(TCommand command)
{
this.decoratee.Handle(command);
this.db.SaveChanges();
}
}
And the form can now depend on ICommandHandler<T>:
public partial class frmMember : Form
{
private readonly ICommandHandler<CreateMemberCommand> commandHandler;
public frmMember(ICommandHandler<CreateMemberCommand> commandHandler)
{
InitializeComponent();
this.commandHandler = commandHandler;
}
private void btnSave_Click(object sender, EventArgs e)
{
this.commandHandler.Handle(
new CreateMemberCommand { MemberName = txtName.Text });
}
}
This can all be registered as follows:
container.Register(typeof(IGenericRepository<>),
typeof(GenericRepository<>));
container.Register(typeof(ICommandHandler<>),
new[] { Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SaveChangesCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(ThreadScopedCommandHandlerDecorator<>),
Lifestyle.Singleton);
This design will remove the need for UnitOfWork and a (specific) service completely.
I'm trying to implement dependency injection but i know how to implement the interface and repository of classes then i don't know what shall i do.
This my sample:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
}
This is my interface:
public interface IUser
{
IEnumerable<User> GetUsers();
void AddUser(User user);
void EditUser(User user);
void DeleteUser(int id);
User UserGetById(int id);
void Save();
}
This is my repository:
public class UserRepsitory:IUser
{
private _Context _context;
public UserRepsitory(_Context _context)
{
this._context = _context;
}
public IEnumerable<User> GetUsers()
{
return _context.User.ToList();
}
public void AddUser(User user)
{
_context.User.Add(user);
}
public void EditUser(User user)
{
_context.Entry(user).State = System.Data.Entity.EntityState.Modified;
}
public User UserGetById(int id)
{
return _context.User.Find(id);
}
public void Save()
{
_context.SaveChanges();
}
public void DeleteUser(int id)
{
var Search = _context.User.Find(id);
_context.User.Remove(Search);
}
}
And one of method in controller:
private IUser userRepsitory;
public UsersController()
{
this.userRepsitory = new UserRepsitory(new _Context());
}
public UsersController(IUser UserRepository)
{
this.userRepsitory = UserRepository;
}
public ActionResult Index()
{
return View(userRepsitory.GetUsers());
}
What is the next step?
The first thing is, get rid of the default constructor where we are hard coding the initialization of UserRepository ! We will do that in the dependency injection way.
public UsersController : Controller
{
private readonly IUser userRepsitory;
public UsersController(IUser UserRepository)
{
this.userRepsitory = UserRepository;
}
public ActionResult Index()
{
return View(userRepsitory.GetUsers());
}
}
Now we need something to tell the MVC framework which version/implementation of IUser should be used when the code runs. you can use any dependency injection frameworks to do that. For example, If you are in MVC 6, you can use the inbuilt dependency injection framework to do that. So go to your Startup class and in your ConfigureServices method, you can map an interface to a concrete implementation.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IUser, UserRepository>();
}
}
If you are in a previous version of MVC, you may consider using any of the dependency injection frameworks available like Unity, Ninject etc.
It is pretty much same, you map an interface to a concrete implementation
Ninject
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUser>().To<UserRepository>();
}
You do not need to put the mapping in a cs file. You can define that in a config file. For example, when you use Unity you can do something like this in your config file (web config or an external config file for unity configuration)
Unity
<alias alias="IUser" type="YourNamespace.IUser, YourAssemblyName" />
<register type="IUser" mapTo="YourNamespace.UseRepository, YourAssemblyName">
In order to create and configure your project with Spring DI(Dependency Feature) you must configure beans.
Create an xml file (if its not there) and add references to bean
In this xml file, provide references to the classes you want to inject. Example:
<bean id="Name of the JAVA Class" class="the Full path of the JAVA class"/>
And in your class where you are supposed to call the referencing class(above), calling procedure would be like :
#Controller
public class MyController {
private full.path.of.my.class.named.MyJavaClass _class;
#Autowired
private MyController (full.path.of.my.class.MyJavaClass class)
{
this._class= class;
}
}
Now say if you a function in MyJavaClass
public int sum(int x, int y){
return x+y;
}
Then without creating object of MyJavaClass you can inject like the following in your controller:
_class.Sum(10,15);
YOU DO NOT CREATE AN INSTANCE OF THIS CLASS.
I am getting "System.StackOverflowException was unhandled" on public
VolunteerDBEntities() : base("name=VolunteerDBEntities", "VolunteerDBEntities")
{
OnContextCreated();
}
It happens when I change this:
public class OrganizationService : IOrganizationService
{
private IValidationDictionary _validationDictionary;
private IOrganizationRepository _repository;
public OrganizationService(IValidationDictionary validationDictionary)
: this(validationDictionary, new OrganizationRepository())
{ }
public OrganizationService(IValidationDictionary validationDictionary, IOrganizationRepository repository)
{
_validationDictionary = validationDictionary;
_repository = repository;
}
...}
To this:
public class OrganizationService : IOrganizationService
{
private IValidationDictionary _validationDictionary;
private IOrganizationRepository _repository;
private ISessionService _session;
public OrganizationService(IValidationDictionary validationDictionary)
: this(validationDictionary, new OrganizationRepository(), new SessionService())
{ }
public OrganizationService(IValidationDictionary validationDictionary, IOrganizationRepository repository, ISessionService session)
{
_validationDictionary = validationDictionary;
_repository = repository;
_session = session;
}
...}
I'm clueless on this one. I set this up for unit testing and anytime I add a class variable to this service, it crashes. I can add a class variable to another services or create a service that replicates this minus the interface and it works. Any ideas?
Session Service Construct:
public class SessionService: ISessionService
{
private IMembershipService _membershipService;
private IVolunteerService _volunteerService;
private IMessageService _messageService;
public SessionService()
: this(new AccountMembershipService(null), new VolunteerService(null), new MessageService())
{}
public SessionService(IMembershipService membershipservice, IVolunteerService volunteerservice, IMessageService messageservice)
{
_membershipService = membershipservice;
_volunteerService = volunteerservice;
_messageService = messageservice;
}
Other Service Constructs:
private IValidationDictionary _validationDictionary;
private IVolunteerRepository _repository;
private IOrganizationService _orgservice;
public VolunteerService(IValidationDictionary validationDictionary)
: this(validationDictionary, new VolunteerRepository(), new OrganizationService(null))
{}
public VolunteerService(IValidationDictionary validationDictionary, IVolunteerRepository repository, IOrganizationService orgservice)
{
_validationDictionary = validationDictionary;
_repository = repository;
_orgservice = orgservice;
}
public class AccountMembershipService : IMembershipService
{
private readonly System.Web.Security.MembershipProvider _provider;
private IValidationDictionary _validationDictionary;
private IVolunteerService _volservice;
private IEmailService _emailservice;
public AccountMembershipService(IValidationDictionary validationDictionary)
: this(validationDictionary, null, new VolunteerService(null), new EmailService())
{
}
public AccountMembershipService(IValidationDictionary validationDictionary, System.Web.Security.MembershipProvider provider, VolunteerService volservice, EmailService emailservice )
{
_validationDictionary = validationDictionary;
_provider = provider ?? Membership.Provider;
_volservice = volservice;
_emailservice = emailservice;
}
You are creating the set of objects recursively.
Your code "smells" with test logic in production because you create all the objects implicitly.
Instead I would encourage to use dependency injection or other solutions so that you do not have hard dependencies in your constructors.
In the worst-case scenario, just use ServiceLocator pattern.
The last option is the easiest way to go for you as you already have too much stuff bound together. Your code would look like this:
public class OrganizationService : IOrganizationService
{
private IValidationDictionary _validationDictionary;
private IOrganizationRepository _repository;
public OrganizationService() {
_validationDictionary = ServiceLocator.Get<IValidationDictionary>();
_repository = ServiceLocator.Get<IOrganizationRepository>();
}
}
Let's look at the dependency on IOrganizationRepository here.
We don't need to know exact type of it. So we don't care. The ServiceLocator is the only body that does care.
Usually it is just a static class (keep in mind multi-threading and synchronization though!).
It can be implemented like this (I don't want to point to existing implementations because it is just too simple to do):
public static class ServiceLocator {
static Func<T, object> _resolver;
public static Setup(Func<T, object> resolver) {
_resolver = resolver;
}
public static TService Get<TService>() {
if (_resolver == null) throw InvalidOperationException("Please Setup first.");
return (TService)_resolver.Invoke(typeof(TService));
}
}
Then in your test setup (probably on the base test class) just do this:
ServiceLocator.Setup(what => {
if (what == typeof(IOrganizationRepository))
return organisationRepository = organisationRepository ?? new OrganizationRepository(); // Singleton
throw new NotSupportedException("The service cannot be resolved: " + what.Name);
});
In production you would instantiate it differently.
Of course it can be easier with CastleWindsor, Microsoft Unity or other dependency injection framework.
Hope that will help.