2013-05-08 3 views
0

Я пытаюсь найти лучший способ разрешить контекстно-зависимые параметры с помощью Autofac. Рассмотрим следующий код:Устранение контекстно-зависимых параметров с помощью Autofac

 builder.RegisterType<SqlDatabaseResourceFactory>().WithParameter("connectionStringKey", "MyConnectionStringKey").As<DatabaseResourceFactory>(); 

     builder.RegisterType<ATypeRepository>().As<IATypeRepository>().PropertiesAutowired(); 
     builder.RegisterType<BTypeRepository>().As<IBTypeRepository>().PropertiesAutowired(); 
     builder.RegisterType<CTypeRepository>().As<ICTypeRepository>().PropertiesAutowired(); 
     builder.RegisterType<DTypeRepository>().As<IDTypeRepository>().PropertiesAutowired(); 

В этом случае каждый «Repository» имеет свойство ResourceFactory, набранный DatabaseResourceFactory, который имеет локальный по умолчанию (для совместимости с унаследованным кодом). Это отлично работает, если все типы, требующие ввода ResourceFactory, используют одну и ту же строку соединения.

Если, скажем, для репозиториев C и D требуется другая строка соединения, это решение больше не будет работать. Лучшая работа вокруг я могу думать о том, чтобы использовать что-то вроде следующего

 builder.RegisterType<ATypeRepository>() 
       .As<IATypeRepository>() 
       .OnActivating(c => c.Instance.ResourceFactory = new SqlDatabaseResourceFactory("MyConnectionStringKey")); 

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

ответ

1

Если, скажем, C и D хранилища необходимы различные строки соединения,

Если C и D нужен другое соединение, они должны получить свои собственные абстракции. Например, определите IBillingDatabaseResourceFactory и IShippingDatabaseResourceFactory. Это устраняет двусмысленность, которая в настоящее время находится в вашем дизайне и конфигурации DI.

+0

Хотя это было бы чисто решить вопрос разрешения зависимостей, кажется, что я бы создать ряд малокровных интерфейсов исключительно с целью дифференциации различных контекстов, в которых было использовано DatabaseResourceFactory (т. е. разные строки соединения). Я не уверен, что имеет смысл связать общий DatabaseResourceFactory (и его дочерние элементы, специфичные для реализации, например SqlDatabaseResourceFactory) для интерфейсов, специфичных для одного домена приложения. –

0

Вы могли бы использовать:

builder.Register(c => new CTypeRepository(new SqlDatabaseResourceFactory("C-connectionstring")).As<ICTypeRepository>().PropertiesAutowired(); 
+0

Это тоже сработает, но, похоже, такая же проблема, как и решение OnActivating, указанное в исходном вопросе. Разве мне не пришлось бы индивидуально регистрировать строку соединения для каждого типа, требующего репозитория? Я надеялся найти решение, в котором я мог бы устранить эту избыточность и каким-то образом указать строки подключения для каждой группы элементов. –

+0

Если у вас может быть несколько строк подключения для разных экземпляров, вы не можете избежать какого-либо определения сопоставления. Подумайте, что каждый раз, когда вы создаете экземпляр, вы должны указать, какой из них. Либо предоставляя его напрямую, либо через интерфейс, либо, возможно, разные экземпляры фабрики, как это предлагают другие. – gabnaim