Stack Overflow issue, Asp.net MVC
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(IV开发者_运维百科alidationDictionary 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.
精彩评论