2012-07-04 2 views
6

я, кажется, делают это справедливый бит в моем коде:Должен ли я явно связывать обычные классы с помощью Autofac?

public class ActionsModule : Module 
    { 
     protected override void Load(ContainerBuilder builder) 
     { 
      base.Load(builder); 
      builder.Register(c => LogManager.GetCurrentClassLogger()).As<ILog>().InstancePerDependency(); 

      // Autofac doesn't seem to be able to inject things without explicit binding 
      builder.RegisterType<ComboActions>().As<ComboActions>().InstancePerHttpRequest(); 
      builder.RegisterType<AppActions>().As<AppActions>().InstancePerHttpRequest(); 
     } 
    } 
} 

Где класс «Действия» класс я требую, чтобы быть введен в мой контроллер, и имеет ряд других суб-зависимости.

Кажется немного хлам. Почему autofac не может решить, что класс имеет конструктор с зависимостями, которые уже удовлетворены и автоматически создают экземпляр?

Я имею в виду, что если класс A требует ввода класса B, а класс B требует достаточно C, D, E и т. Д., Я думаю, вы не хотите ходить по всей цепочке зависимостей, чтобы увидеть, можете ли вы сделать класс во время выполнения. ... но если класс А напрямую зависит от C и D, которые явно связаны, то это тривиальный случай?

Я что-то упустил? Кажется, не вижу никакой документации для этого ...

ответ

2

AFAIK, Autofac требует, чтобы каждый необходимый тип регистрировался в контейнере, но это не значит, что вы должны делать каждый по отдельности. Почти 99% моих регистраций обрабатываются путем добавления этого атрибута к типу:

[AttributeUsage(AttributeTargets.Class)] 
public class AutoRegisterAttribute : Attribute { } 

Так, например, вы бы

[AutoRegister] 
class ComboActions 
{ 

А затем зарегистрировать их с этим:

public class AutoScanModule : Module 
{ 
    private readonly Assembly[] _assembliesToScan; 

    public AutoScanModule(params Assembly[] assembliesToScan) 
    { 
     _assembliesToScan = assembliesToScan; 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterAssemblyTypes(_assembliesToScan) 
      .Where(t => t.GetCustomAttributes(typeof (AutoRegisterAttribute), false).Any()) 
      .AsSelf() 
      .AsImplementedInterfaces() 
      .InstancePerLifetimeScope(); 
    } 
} 

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

EDIT: Проверьте reply from Kaleb, что доказывает, что я ошибаюсь. Я никогда не знал об этом!

20

Вам не нужно регистрировать все типы. Autofac предоставляет AnyConcreteTypeNotAlreadyRegisteredSource, который автоматически захватит конкретный тип, если вы еще не зарегистрировали регистрацию.

Например:

var builder = new ContainerBuilder(); 
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource()); 
var container = builder.Build(); 
... 
var myConcreteType = container.Resolve<MyConcreteType>(); 

источники позволяют более сложные вещи, такие как automatically injecting mocked objects для интерфейсов и зависимостей на основе абстрактных классов.

+0

Whoah. Никогда не знал об этом. TIL! –

+1

это УДИВИТЕЛЬНО, тем более, что вы можете сделать что-то вроде 'builder.RegisterSource (новый AnyConcreteTypeNotAlreadyRegisteredSource (x => x.Name.Contains (" ViewModel ")));' –

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