6 / 6 / 1
Регистрация: 25.02.2016
Сообщений: 335
1

Autofac Инъекция в метод

21.07.2016, 02:57. Показов 4747. Ответов 22
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
Есть у меня контейнер с необходимыми зависимостями, помеченными SingleInstance.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var builder = new ContainerBuilder();
builder.RegisterType<A>().AsSelf().SingleInstance();
builder.RegisterType<B>().AsSelf().SingleInstance();
//A и B - какие-то произвольные классы
var container = builder.Build();
var obj = container.Resolve<C>(); //Для удобства класс C ниже
 
class C
{
     public C(A a, B b)
     {
         //Все хорошо, зависимости переданы
     }
 
     public Foo(A a, B b)
     {
        //Если ли варианты, чтобы получить эти зависимости здесь?
     }
}
"Если ли варианты, чтобы получить эти зависимости здесь?" - проблемы бы не было, если бы параметры были именно A и B. Проблема в том, что я хочу добиться эффекта, как с конструктором - в конструкторе пишу нужное количество параметров в нужном мне порядке и Autofac сам подставляет зависимости.
Можно ли как-нибудь вызвать метод объекта с передачей туда зависимостей, количество которых неизвестно?
Грубо говоря, что-то типа этого:
C#
1
container.Resolve<C>(Foo); //Параметры для Foo сами подставятся ???
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.07.2016, 02:57
Ответы с готовыми решениями:

ASP + Autofac + SignalR
Добрый день, столкнулся со следующий проблемой, нужно Autofac отрезолвить ILifetimeScope в...

Взаимная работа MvcSiteMapProvider с Autofac?
У себя на сайте, для реализации хлебных крошек заюзал MvcSiteMapProvider. Также а сайте использую...

Как правильно произносится Autofac (Dependecy Injection)
Привет. Я догадываюсь, что можно на ютубе посмотреть несколько видюх и какой-то да произнесут. Но я...

php инъекция
Доброе время суток. Помогите пожалуйста разобраться с php инъекцией. Есть форма авторизации и к...

22
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
21.07.2016, 05:04 2
Kertis138, сама идея внедрения зависимостей базируется на работе не с экземплярами конкретных классов, а с интерфейсами (на крайний случай - с абстрактными классами). Это даёт возможность менять реализацию интерфейса в любой момент (для тестирования или при расширении возможностей ПО). А вот конструкция вида builder.RegisterType<A>().AsSelf().SingleInstance(); ничем не лучше простого new A();,но, при этом, значительно всё усложняет - твой класс С как был привязан к классам А и В так и остался, только добавилась портянка из IoC-контейнера.

Цитата Сообщение от Kertis138 Посмотреть сообщение
Можно ли как-нибудь вызвать метод объекта с передачей туда зависимостей, количество которых неизвестно?
Нет.
0
6 / 6 / 1
Регистрация: 25.02.2016
Сообщений: 335
21.07.2016, 10:04  [ТС] 3
Цитата Сообщение от Usaga Посмотреть сообщение
сама идея внедрения зависимостей базируется на работе не с экземплярами конкретных классов, а с интерфейсами (на крайний случай - с абстрактными классами).
У меня есть базовый абстрактный класс и от него наследуются многие подклассы. Сама идея была - в зависимостях получать те подклассы, которые необходимы. Почему не конструктор? Потому что может случится ситуация, когда два класса будут просить друг друга, а так как передача ссылок будет производиться в конструкторе, то вылетает ошибка.
Подскажите, какие образом тогда сделать общение между подклассами(модулями), которые наследуются от одного интерфейса?
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
21.07.2016, 10:18 4
Цитата Сообщение от Kertis138 Посмотреть сообщение
У меня есть базовый абстрактный класс и от него наследуются многие подклассы.
Вот этот базовый класс и нужно использовать как зависимость. Но лучше, всё-таки, интерфейс.

Цитата Сообщение от Kertis138 Посмотреть сообщение
Потому что может случится ситуация, когда два класса будут просить друг друга
Тогда зависимость одно из таких классов нужно инжектировать не в конструктор, а в свойство.

Цитата Сообщение от Kertis138 Посмотреть сообщение
Подскажите, какие образом тогда сделать общение между подклассами(модулями), которые наследуются от одного интерфейса?
Какого плана общение?
0
6 / 6 / 1
Регистрация: 25.02.2016
Сообщений: 335
21.07.2016, 10:23  [ТС] 5
Цитата Сообщение от Usaga Посмотреть сообщение
Какого плана общение?
Общая схема такая:
интерфейс - IModule
и производные классы A,B,C...
Один модуль может получить другой и вызвать его метод и и любая другая необходимая работа.
А если все классы A,B,C... регистрируются вот так builder.RegisterType(X).AsSelf(<IModule>).SingleInstance();
То свойства надо сделать публичными и типа IModule?
Просто не пойму, получается я регистрирую все под типом IModule, а что тогда Autofac подставлять будет, если вариантов много?
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
21.07.2016, 10:30 6
Цитата Сообщение от Kertis138 Посмотреть сообщение
регистрируются вот так builder.RegisterType(X).AsSelf(<IModule>).SingleInstance();
Правильнее было бы так: builder.RegisterType<SomeClass>().AsImplementedInterfaces();

Цитата Сообщение от Kertis138 Посмотреть сообщение
Просто не пойму, получается я регистрирую все под типом IModule, а что тогда Autofac подставлять будет, если вариантов много?
AutoFac будет выдавать последний зарегистрированный для этого интерфейса класс. В таком случае, рекомендую использовать свою собственную фабрику (которую внедрять в потребителей через тот же AutoFac), в которой разместить логику определения, когда какой реальный класс создавать для текущего потребителя.
1
6 / 6 / 1
Регистрация: 25.02.2016
Сообщений: 335
21.07.2016, 10:45  [ТС] 7
Цитата Сообщение от Usaga Посмотреть сообщение
сама идея внедрения зависимостей базируется на работе не с экземплярами конкретных классов, а с интерфейсами (на крайний случай - с абстрактными классами). Это даёт возможность менять реализацию интерфейса в любой момент
Менять реализацию интерфейса - это значит перестраивать производный класс на основе изменений в базовом?
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
21.07.2016, 11:02 8
Лучший ответ Сообщение было отмечено Kertis138 как решение

Решение

Интерфейс != базовый класс. Он просто описывает... эм... интерфейс твоего будущего класса (сигнатуры методов и свойств). Менять реализацию, значит менять логику класса реализующего данный интерфейс, но не менять сам интерфейс. Т.е. интерфейс всегда один, но что в реале за ним скрыто - одному Богу известно (и тебе).
2
5 / 4 / 1
Регистрация: 24.09.2016
Сообщений: 398
06.12.2023, 00:11 9
Usaga,
Цитата Сообщение от Usaga Посмотреть сообщение
использовать свою собственную фабрику (которую внедрять в потребителей через тот же AutoFac), в которой разместить логику определения, когда какой реальный класс создавать для текущего потребителя.
дайте пожалста ссылочку на такой примерчик
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
06.12.2023, 05:12 10
Цитата Сообщение от DLD Посмотреть сообщение
дайте пожалста ссылочку на такой примерчик
Это стандартный паттерн проектирования "Factory".
0
5 / 4 / 1
Регистрация: 24.09.2016
Сообщений: 398
06.12.2023, 09:07 11
Usaga, по паттерну фабрика инфы много, меня интересует именно с использованием Autofac . . . думал - может вы порекомендуете примерчик по-проще на c#
0
HF
1162 / 748 / 181
Регистрация: 09.09.2011
Сообщений: 2,312
Записей в блоге: 2
06.12.2023, 09:59 12
Цитата Сообщение от Kertis138 Посмотреть сообщение
в конструкторе пишу нужное количество параметров в нужном мне порядке и Autofac сам подставляет зависимости.

Сама идея была - в зависимостях получать те подклассы, которые необходимы. Почему не конструктор? Потому что может случится ситуация, когда два класса будут просить друг друга, а так как передача ссылок будет производиться в конструкторе, то вылетает ошибка.
Разве эта сама идея - не смысл работы библиотек внедрения зависимостей.
"хочу в конструкторе подставлять зависимости" = "хочу сделать свой DI"

Цитата Сообщение от Kertis138 Посмотреть сообщение
У меня есть базовый абстрактный класс и от него наследуются многие подклассы.
Подскажите, какие образом тогда сделать общение между подклассами(модулями), которые наследуются от одного интерфейса?
Считаю вот тут и корень проблемы. Можно даже создать коллекцию зависимостей одного типа, но это делается для возможности их использовать в ситуации когда неизвестен нужный тип, но его можно найти. Например, рендеры для разных типов объектов. Я перебираю коллекцию и нахожу нужный тип по какому-то флагу.
Но они не должны и не могут между собой "общаться". Это значит сделанная архитектура на столько неправильная, что пришлось придумывать обходные пути - получить какие-то данные, состояния, значения из одного места в другом. Ну дак значит они и должны быть в других местах, не связанных с этими классами.
0
2294 / 1658 / 325
Регистрация: 14.08.2018
Сообщений: 5,453
Записей в блоге: 4
06.12.2023, 10:01 13
HF, Эммм... Этому вопросу от ТС уже 7 лет...
1
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
06.12.2023, 11:15 14
Цитата Сообщение от DLD Посмотреть сообщение
по паттерну фабрика инфы много, меня интересует именно с использованием Autofac . . . думал - может вы порекомендуете примерчик по-проще на c#
А в чём ты видишь сложность совместить фабрику с автофаком? Регистрируешь как обычный сервис. Тут отличий особых нет. Разве что, если сервисы, которые фабрика должна пораждать, сами создаются через автофак, то надо в конструктор фабрики заинжектить IServiceLocator и всё.
0
5 / 4 / 1
Регистрация: 24.09.2016
Сообщений: 398
06.12.2023, 11:58 15
Usaga, прежде чем самому что-то порождать - решил воспользоваться примером из ресурса Autofac. Но он не полный - потому ошибки. Не могли бы вы его завершить чтобы можно было его запустить в Студии ?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using Autofac;
namespace ConsoleApp1
{
  public interface IQuoteService { decimal GetQuote(string symbol); }
  class Program
  {
    private static void Main(string[] args)
    {
      var builder = new ContainerBuilder();
      builder.RegisterType<Shareholding>();
      builder.RegisterType<Portfolio>();    
      builder.RegisterType<WebQuoteService>().As<IQuoteService>();
      using var container = builder.Build();
 
      using var scope = container.BeginLifetimeScope();
      var createHolding = scope.Resolve<Shareholding.Factory>();
 
      var portfolio = scope.Resolve<Portfolio>();
      portfolio.Add("DEF", 4324); 
 
      Console.Read();
    }
  }
 
  public class Portfolio
  {
    private readonly Shareholding.Factory _shareHoldingFactory;
    private readonly List<Shareholding> _holdings = new List<Shareholding>();
    public Portfolio(Shareholding.Factory shareholdingFactory) => _shareHoldingFactory = shareholdingFactory;
    public void Add(string symbol, int holding)
    {
      _holdings.Add(_shareHoldingFactory(symbol, holding));
    }
    public decimal CurrentValue()
    {
      return _holdings.Aggregate(0m, (agg, holding) => agg + holding.CurrentValue());
    }
  }
  internal class WebQuoteService : IQuoteService
  {
    public decimal GetQuote(string symbol)
    {
      throw new NotImplementedException();
    }
  }
  public class Shareholding
  {
    public delegate Shareholding Factory(string symbol, int holding);
    public string Symbol { get; private set; }
    public int Holding { get; set; }
    private readonly IQuoteService _quoteService;
    internal Shareholding(string symbol, int holding, IQuoteService quoteService)
    {
      Symbol = symbol;
      Holding = holding;
      _quoteService = quoteService;
    }
    public decimal CurrentValue()
    {
      return _quoteService.GetQuote(Symbol) * Holding;
    }
  }
}
0
2294 / 1658 / 325
Регистрация: 14.08.2018
Сообщений: 5,453
Записей в блоге: 4
06.12.2023, 12:46 16
Цитата Сообщение от DLD Посмотреть сообщение
Autofac
А вам точно это нужно? Чем не устраивает родной DI от Microsoft?
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
06.12.2023, 12:51 17
DLD, а что ты тут пытался реализовать?)
0
5 / 4 / 1
Регистрация: 24.09.2016
Сообщений: 398
06.12.2023, 13:15 18
Andrey-MSK, все хвалят что в Autofac поддержка лучше . . . к тому же кучу времени убил пока теорию читал . . . С другой стороны, даже если Autofac и DI от Microsoft равноценны - то кто-то задаст аналогичный вопрос - почему выбрал именно DI от Microsoft, а не Autofac
0
2294 / 1658 / 325
Регистрация: 14.08.2018
Сообщений: 5,453
Записей в блоге: 4
06.12.2023, 13:34 19
Цитата Сообщение от DLD Посмотреть сообщение
почему выбрал именно DI от Microsoft
Работает в три строчки кода.

Добавлено через 4 минуты
DLD, Dependency injection in WPF project with .net core
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public IServiceProvider ServiceProvider { get; private set; }
 
public IConfiguration Configuration { get; private set; }
 
protected override void OnStartup(StartupEventArgs e)
{
    var builder = new ConfigurationBuilder()
     .SetBasePath(Directory.GetCurrentDirectory())
     .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
 
    Configuration = builder.Build();
 
    var serviceCollection = new ServiceCollection();
    ConfigureServices(serviceCollection);
 
    ServiceProvider = serviceCollection.BuildServiceProvider();
 
    var mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
    mainWindow.Show();
}
 
private void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));
 
    services.AddTransient(typeof(MainWindow));
}
Добавлено через 1 минуту
Тут очень топорно сделано, но общую картину показывает.

Добавлено через 10 минут
DLD, И потом просто инжектим нужные сервисы куда надо
C#
1
2
3
4
5
6
7
8
public HBMachineDialogVM(IWindowService windowService,
                         IBackgroundTaskQueue taskQueue,
                         IMainDA mainDA)
{
    _windowService = windowService;
    _taskQueue = taskQueue;
    _mainDA = mainDA;
}
1
5 / 4 / 1
Регистрация: 24.09.2016
Сообщений: 398
06.12.2023, 13:44 20
Usaga Пример взят отсюда
Я так понимаю. Тут при помощи фабрики делегатов нужно создать экземпляр класса, в котором при помощи метода GetQuote() будет инфа по акции: "ABC", 1234

Добавлено через 7 минут
Andrey-MSK, спасибо большое . . . Однако . . . лично я не могу на данный момент времени постигнуть все разнообразие фреймворков, поэтому рассматриваю законченные проекты - попроще, которые запускаются в Консольном приложении - чтобы можно было пошагово пройтись по коду
0
06.12.2023, 13:44
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.12.2023, 13:44
Помогаю со студенческими работами здесь

SQL инъекция
Здравствуйте. Мне сообщили, что в коде одного из плагинов сайта существует возможность включения...

Инъекция кода. C#
Я создал пустую форму. Как с помощью инъекции дописать в нее вызов, например меседжбокса? ...

Инъекция и Сюръекция
Допустим X,Y и Z не пустые множества и f : X → Y и g : Y → Z функции. Доказать, что если g...

Инъекция кода
Есть Access файл с дополнительными надстройками наверное на vbs. Текущий код не проверяет...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru