Проблема переполнения стека, Asp.net MVC - PullRequest
0 голосов
/ 11 ноября 2010

Я получаю сообщение «System.StackOverflowException не обработан» в общедоступном

VolunteerDBEntities() : base("name=VolunteerDBEntities", "VolunteerDBEntities")
        {
            OnContextCreated();
        }

Это происходит, когда я меняю это:

   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;
        }
...}

К этому:

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;
        }
...}

Я не в курсе этого. Я настроил это для модульного тестирования, и каждый раз, когда я добавляю переменную класса в этот сервис, он падает. Я могу добавить переменную класса в другие сервисы или создать сервис, который копирует это без интерфейса, и это работает. Есть идеи?

Конструкция службы сеанса:

   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;
        }

Другие сервисные конструкции:

private IValidationDictionary _validationDictionary; частный репозиторий IVolunteer _repository; частный 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;
    }

1 Ответ

1 голос
/ 11 ноября 2010

Вы создаете набор объектов рекурсивно.

Ваш код "пахнет" тестовой логикой в ​​производстве , потому что вы создаете все объекты неявно.

Вместо этого я рекомендую использовать внедрение зависимостей или другие решения чтобы у вас не было жестких зависимостей в ваших конструкторах.

В худшем случае , просто используйте ServiceLocator шаблон.

Последний вариант - самый простой способ для вас, так как у вас уже есть слишком много вещей, связанных вместе.Ваш код будет выглядеть так:

   public class OrganizationService : IOrganizationService
    {

        private IValidationDictionary _validationDictionary;
        private IOrganizationRepository _repository;

        public OrganizationService() {
            _validationDictionary = ServiceLocator.Get<IValidationDictionary>();
            _repository = ServiceLocator.Get<IOrganizationRepository>();
        }
    }

Давайте посмотрим на зависимость от IOrganizationRepository здесь.

Нам не нужно знать точный тип этого.Так что нам все равно.ServiceLocator - это единственное тело, которое заботится.

Обычно это просто статический класс (помните о многопоточности и синхронизации!).

Он может быть реализован следующим образом(Я не хочу указывать на существующие реализации, потому что это слишком просто сделать):

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));
    }
}

Затем в вашей тестовой настройке (возможно, в базовом тестовом классе) просто сделайте это:

ServiceLocator.Setup(what => {
    if (what == typeof(IOrganizationRepository))
        return organisationRepository = organisationRepository ?? new OrganizationRepository(); // Singleton
    throw new NotSupportedException("The service cannot be resolved: " + what.Name);
});

В производственном процессе вы могли бы создать его по-другому.

Конечно, это может быть проще с CastleWindsor, Microsoft Unity или другой структурой внедрения зависимостей.

Надеюсь, это поможет.

...