Могу ли я иметь условное построение классов при использовании IoC.Resolve? - PullRequest
1 голос
/ 08 апреля 2010

У меня есть класс обслуживания, который перегружен конструкторами. Один конструктор имеет 5 параметров, а другой - 4.

Прежде чем позвонить,

var service = IoC.Resolve<IService>();

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

        bool testPassed = CheckCertainConditions();
        if (testPassed)
        {
            //Resolve service using 5 paramater constructor
        }
        else
        {
            //Resolve service using 4 parameter constructor
            //If I use 5 parameter constructor under these conditions I will have epic fail.
        }

Можно ли указать, какой из них я хочу использовать?

Ответы [ 2 ]

2 голосов
/ 08 апреля 2010

В общем, вы должны следить за неоднозначностью в конструкторах, когда дело доходит до DI, потому что вы, по сути, говорите любому вызывающему абоненту, что 'Мне действительно все равно, используете ли вы один или другие ". Это вряд ли то, что вы хотели.

Однако одно независимое от контейнера решение состоит в том, чтобы заключить условную реализацию в другой класс, реализующий тот же интерфейс:

public class ConditionalService : IService
{
    private readonly IService service;

    public ConditionalService()
    {
        bool testPassed = CheckCertainConditions();      
        if (testPassed)      
        {      
            // assign this.service using 5 paramater constructor      
        }      
        else      
        {      
            // assign this.service using 4 parameter constructor
        }  
    }

    // assuming that IService has a Foo method:
    public IBaz Foo(IBar bar)
    {
        return this.service.Foo(bar);
    }
}

Если вы не можете выполнить проверку CheckCertainConditions в конструкторе, вы можете вместо этого использовать Ленивая оценка .

Было бы неплохо разрешить ConditionalService запрашивать все зависимости через Внедрение в конструктор , но я оставил это в примере кода.

Вы можете зарегистрировать ConditionalService с DI-контейнером вместо реальной реализации.

0 голосов
/ 13 апреля 2010

Моя основная проблема заключалась в том, что я пытался разрешить свой класс со следующей подписью:

public DatabaseSchemaSynchronisationService(IDatabaseService databaseService, IUserSessionManager userSessionManager)

Это было в принципе бесполезно для меня, потому что у моего usersessionmanager не было активного NHibernate.ISession, потому что соединение с моимБаза данных еще не была создана.Я пытался проверить, было ли у меня соединение, и только затем разрешить этот класс, который служил в качестве службы для запуска сценариев обновления базы данных.

При изменении всего класса для выполнения сценариев другим способомвсе, что мне было нужно в подписи его конструктора:

public DatabaseSchemaSynchronisationService(ISessionFactory sessionFactory)

Это позволило мне открыть мой собственный сеанс.Однако мне пришлось сначала проверить, было ли готово соединение, прежде чем пытаться разрешить класс, но иметь IDatabaseSchemaSynchronisationService в качестве параметра для конструктора другого класса;этот класс также разрешается где-то, где я не могу проверить соединение с БД, было плохой идеей.

Вместо этого во втором классе я вычеркнул параметр IDatabaseSchemaSynchronisationService из сигнатуры конструктора и сделал его локальной переменной, для которой создается только экземпляр (решен):

if (connectionIsReady)

Спасибо всем, кто ответил.

...