2016-06-22 3 views
1

Я использую MVC с EF и Autofac. У меня есть конкретный класс под названием «Помощник». Помощник находится в другой DLL, а не в основном веб-приложении MVC.Autofac Property Inject issues

Он имеет свойство типа DBContext, называемое «Контекст».

Я хочу ввести экземпляр DBContext в это свойство, но его всегда null.

Вот то, что я до сих пор в Глобально:

var output = new DbContext(connectionString); 
    builder.RegisterInstance(output).As<DbContext>().PropertiesAutowired(); 
      builder.RegisterType<Helper().WithParameter("Context",output).PropertiesAutowired(); 

     // Set the dependency resolver to be Autofac. 
     var container = builder.Build(); 
     DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

Контекст свойство в классе Helper, который я хотел бы впрыскивается с экземпляром «выходной».

Контекст всегда равен нулю.

+0

Не могли бы вы дать подпись конструктора класса Helper? Насколько я могу судить, либо вам нужен параметр WithParameter OR PropertiesAutowired, но не тот и другой. И, возможно, вам и этого не нужно, если у вас есть параметр типа DbContext в вашем конструкторе Helper. –

+0

Спасибо за ваш ответ. Я просто пустой конструктор, т. Е. Public Helper() {}. – Chris

+0

Не могли бы вы поделиться кодом свойства Context? Является ли он общедоступным и читается/записывается? –

ответ

8

В Autofac самым простым способом управления зависимостями является использование инъекции конструктора.

В принципе, вместо того, чтобы сообщать Autofac «подключите свойства для меня и сделайте свое mojo», вы говорите ему, чтобы вы отвечали за объявление списка компонентов.

Таким образом, вместо того, чтобы задаваться вопросом, почему инъекции свойства не работают, объявлять явно свою зависимость в Helper конструктору:

public class Helper 
{ 
    public DbContext Context { get; private set; } 

    public Helper(DbContext context /* Autofac is going to fill in this */) 
    { 
     Context = context; 
    } 
} 

Затем в Global (или в каком-то другом классе герметизирующей ваши регистраций) вы просто скажите Autofac к посмотреть на Helper типа и стараться изо всех сил, чтобы назвать лучший конструктор, который является самым простым, что вы можете сделать:

// Either InstancePerDependency, or SingleInstance, or something else depending upon you requirements. 
builder.RegisterType<Helper>().AsSelf().InstancePerDependency(); 

и вы должны сделать: Autofac будет искать конструктору с большинством параметров (и Ther e будет только один с параметром типа DbContext и проверит, знает ли он, как создавать параметры для запрашиваемого типа (что он может).

Итак, вуаля, вы получите готовый к использованию помощник!

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

public class Helper 
{ 
    public DbContext Context { get; private set; } 

    public Init(DbContext context /* Autofac is going to fill in this */) 
    { 
     Context = context; 
    } 
} 

И вы можете поручить Autofac вызывать этот метод во время инициализации объекта:

builder.RegisterType<CustomHelper>().AsSelf().InstancePerDependency() 
    .OnActivating(h => { 
     var dbContext = h.Context.Resolve<DbContext>(); 
     ((Helper)h.Instance).Init(context); 
    }); 

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

+0

Спасибо за ваш ответ. Это идеальная ситуация, однако Helper является базовым классом, и я не хочу, чтобы какой-либо класс, который наследует Helper, должен также иметь DbContext в своем конструкторе.Есть ли способ autofac, который может заставить систему использовать перегруженный конструктор с DbContext? Еще раз спасибо. – Chris

+0

Спасибо за ваш ответ. Это хорошая работа. Тем не менее, я оставил точку останова на методе Init, и он никогда не называется. Вот мой глобальный: var output = new DbContext (connectionString); builder.RegisterType () .AsSelf() InstancePerDependency() .OnActivating. (Ч => { ((BaseHelper) h.Instance) .init (выход); }); – Chris

+0

Наследование не очень дружественное к DI. Лучшим подходом было бы изменить дизайн (если это возможно), чтобы использовать более DI-образный шаблон, такой как Decorator или Proxy, поэтому зависимость 'DbContext' не будет напрямую требоваться вашим конкретным экземпляром. Посмотрите, как [фильтры] (http://stackoverflow.com/a/28365933/181087) работают в MVC для вдохновения. – NightOwl888