2010-03-19 3 views
4

Я использую Autofac. Я хочу добавить другую реализацию зависимости на основе атрибута, который я применяю к параметру конструктора. Например:Разрешить зависимость с autofac на основе атрибута параметра конструктора

class CustomerRepository 
{ 
    public CustomerRepository([CustomerDB] IObjectContainer db) { ... } 
} 

class FooRepository 
{ 
    public FooRepository([FooDB] IObjectContainer db) { ... } 
} 

builder.Register(c => /* return different instance based on attribute on the parameter */) 
     .As<IObjectContainer>(); 

Атрибуты будет предоставлять данные, такие как строки подключения, который можно использовать, чтобы, например правильный объект.

Как я могу это сделать?

ответ

9

Похоже, что вы хотите предоставить различные варианты использования IObjectContainer по умолчанию CustomerRepository и FooRepository. Если это так, атрибуты могут быть thin metal ruler. Вместо этого я покажу вам, как реализовать множество реализаций с помощью Autofac.

(вызовы, такие как .ContainerScoped() были опущены для краткости.)

Во-первых, зарегистрировать версию IObjectContainer для каждой строки подключения, назвав регистрации:

builder 
    .Register(c => new ObjectContainer(ConnectionStrings.CustomerDB)) 
    .As<IObjectContainer>() 
    .Named("CustomerObjectContainer"); 

builder 
    .Register(c => new ObjectContainer(ConnectionStrings.FooDB)) 
    .As<IObjectContainer>() 
    .Named("FooObjectContainer"); 

Тогда, решить конкретные случаи в хранилище регистрации:

builder.Register(c => new CustomerRepository(
    c.Resolve<IObjectContainer>("CustomerObjectContainer")); 

builder.Register(c => new FooRepository(
    c.Resolve<IObjectContainer>("FooObjectContainer")); 

Это оставляет репозитории бесплатно информации о конфигурации:

class CustomerRepository 
{ 
    public CustomerRepository(IObjectContainer db) { ... } 
} 

class FooRepository 
{ 
    public FooRepository(IObjectContainer db) { ... } 
} 
+0

Спасибо за отличный ответ. Вы поднимаете справедливую точку зрения о том, что хранилища не имеют конфигурации. Тем не менее, я по-прежнему хочу, чтобы AutoFac мог обеспечить удобный контекст для выбора служб. Я знаю, что Ninject может это сделать. Я мог бы пойти по пути ввода Func . Таким образом, репозиторий может решить, что он хочет. –

+2

Autofac (нижний регистр) может поддерживать буквально любой тип настраиваемой контекстно-зависимой конструкции, которую вы хотите. Это связано с тем, что 'Register ' может принимать лямбда-выражение ('Func <>'), и вы можете создавать лямбда-выражения с помощью деревьев выражений (http://msdn.microsoft.com/en-us/library/bb397951.aspx) , Это означает, что вы можете использовать рефлексию для создания любой лямбды, необходимой для выполнения пользовательской конструкции. –

+0

Кажется, вы хотите, чтобы репозитории соединялись со строками подключения, либо с помощью атрибутов, либо с помощью аргументов 'Func '. Я спрашиваю в ответ: почему репозиторий должен знать строку соединения? Если нужно создать «IObjectContainer», разве это не ответственность за конфигурацию типа * that *? Почему репозиторий даже должен знать строку соединения? Почему бы просто не принять «IObjectContainer»? –

0

Ответ Брайана достаточно хорош, в то время как у вас есть несколько репозиториев, и у них мало параметров конструктора. Но трудно установить свой корень, когда у вас их много. Это можно сделать, сканировав метаданные класса при разрешении интерфейса. Когда вы получаете информацию о своих параметрах, вы можете решить ее фактическую реализацию. См. Мой ответ here.

Смежные вопросы