powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / IoC. Постепенный перевод проекта. Возможно ли
25 сообщений из 47, страница 1 из 2
IoC. Постепенный перевод проекта. Возможно ли
    #38628469
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Попробовал перевести проект на IoC. но не сразу все, а постепенно.
Возможно ли такое или придется все сразу переделывать?

И еще вопрос с реализацией. Использую Autofac пока. На нем тренируюсь.
Начал с репозиторий. Взял 1 из репозиторий, она является самостоятельным классом и реализовал интерфейс.
Теперь класс выглядит так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
 internal class UserRepository : IUserRepository
	{
		private ModelDataContext _dataManager;

		public UserRepository(ModelDataContext DataContext)
		{
			_dataManager = DataContext;
		}
..........................................



Прописал при запуске конфигурацию IoC
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
private static void ConfigureIoC()
        {
            var builder = new ContainerBuilder();
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            // register repositories
            builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerHttpRequest();

            IContainer container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
        }



Теперь вопрос, как поступить вот с этим:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
public class DataManager
	{
		private ModelDataContextWrapper _dataContext;
		public DataManager()
		{
			_dataContext = new ModelDataContextWrapper();
		}

        private IUserRepository _userRepository;
        public IUserRepository Users;
		{
			get 
			{
				if (null == _userRepository)
					_userRepository = new UserRepository(_dataContext);

				return _userRepository;
			}
		}



Если я все правильно понимаю, то данный класс должен быть также наследовать интерфейс IDataManager?
Что здесь лишнее или что я забыл, чтобы часть, а именно UserRepository заработала, как DI?
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628586
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaВозможно ли такое или придется все сразу переделывать?

возможно. но рекомендую задаться целью, для чего вам нужен DI, и какие преимуществ конкретно вы хотите добиться? так вам будет проще, чем тупо "переводить всё на DI".


PavluhaЧто здесь лишнее или что я забыл, чтобы часть, а именно UserRepository заработала, как DI?

старайтесь передавать зависимости через конструктор:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
        public class DataManager : IDataManager
	{		
                public DataManager(IUserRepository repository)
		{
			// _dataContext = new ModelDataContextWrapper(); --- НЕТ!
                        _userRepository = repository;  // ДА!
		}

        private IUserRepository _userRepository;
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628591
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pavluha,

если где-то получается, что компонент требует много зависимостей (и вам кажется, что конструктор от этого распух), значит проблема в архитектуре.

также постарайтесь избежать "аггрегатора" зависимостей, собирающего кучу зависимостей и раздающего направо и налево. лучше передать фабрику на базе DI-контейнера.

Autofac, кстати, хороший выбор.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628637
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Сейчас сделал так и пока работает, но хотелось бы комментариев на правильность:
Код: 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.
public interface IDataManager: IDisposable
    {
        ModelDataContextWrapper Get();
    
        IUserRepository Users { get; }
}
public class DataManager: IDataManager, IDisposable
	{
		private ModelDataContextWrapper _dataContext;
		public DataManager()
		{
			Get();
		}
private IUserRepository _userRepository;
        public IUserRepository Users
        {
            get
            {
                if (null == _userRepository)
                    _userRepository = DependencyResolver.Current.GetService<IUserRepository>();

                return _userRepository;
            }
        }

public ModelDataContextWrapper Get()
        {
            return _dataContext ?? (_dataContext = new ModelDataContextWrapper());
        }
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628678
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaСейчас сделал так и пока работает, но хотелось бы комментариев на правильность:

плохо.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
        private IUserRepository _userRepository;
        public IUserRepository Users
        {
            get
            {
                if (null == _userRepository)
                    _userRepository = DependencyResolver.Current.GetService<IUserRepository>();

                return _userRepository;
            }
        }



получайте IUserRepository через конструктор (как я показал выше).

и постарайтесь свести использование DependencyResolver к минимуму. желательно, чтобы он вообще не появлялся, ну кроме тех мест, где механизм разрешения зависимостей DI недоступен (например, в HttpApplication).

и ещё один момент. у вас IDataManager выполняет роль DI, отдавая ModelDataContextWrapper с помощью метода Get(). зачем? получайте свой ModelDataContextWrapper точно также через DI. или через фабрику. а вообще при использовании репозитория, дата контекст вообще не нужен.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628795
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVosttполучайте свой ModelDataContextWrapper точно также через DI

А пример можно?
Просто у меня модель используется DBML не EF. В инете ничего путного не нашел.
А сам DataManager это менеджер репозиторий с lazy инициализацией.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628806
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Вроде начал догонять.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
public class DataManager : IDataManager
	{		
                public DataManager(IUserRepository repository)
		{
                        _userRepository = repository;  // ДА!
		}

        private IUserRepository _userRepository;



У меня репозиторий вот столько:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public interface IDataManager: IDisposable
    {
        ModelDataContextWrapper Get();
    
        IUserRepository Users { get; }
        RoleRepository Roles { get; }
        CDMRepository CDMs { get; }
        CommandRepository Commands { get; }
        AuditRepository Audits { get; }
        MonitoringRepository Monitorings { get; }
        SettingRepository Settings { get; }

        void SubmitChanges();
    }



Их все в конструкторе указывать?
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628875
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Фабрику реализовал:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public class DatabaseFactory : IDisposable, IDatabaseFactory
    {
        private ModelDataContextWrapper _entityContext;
        public ModelDataContextWrapper Get()
        {
            return _entityContext ?? (_entityContext = new ModelDataContextWrapper());
        }

        public void Dispose()
        {
            if (null != _entityContext)
                _entityContext.Dispose();
        }
    }



Теперь вообще запутался, куда и как ее прикручивать (((
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628883
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaТеперь вообще запутался, куда и как ее прикручивать (((

не-не..

Код: c#
1.
builder.RegisterType<ModelDataContextWrapper>().As<IModelDataContext>().InstancePerLifetimeScope();



и получайте где требуется IModelDataContext. незачем пилить свою собственную фабрику, если не планируется использовать её как точку расширения, или не используются дополнительные вариативные зависимости.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628888
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

IModelDataContext не реализован, да и как его реализовать понятия не имею.
В EF как-то файл *.tt переписывали, а с dbml вообще непонятно или все не так понимаю?
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628891
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaИх все в конструкторе указывать?

указывайте в конструкторе только те, которые реально используются. зачем все?

а SubmitChanges() я бы вынес отдельно:

Код: c#
1.
2.
3.
4.
5.
6.
    public interface IUnitOfWork
    {
        int Save();
        Task<int> SaveAsync();
        Task<int> SaveAsync(CancellationToken cancellationToken);
    }
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628892
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А если вот так сделать

Код: c#
1.
builder.RegisterType<ModelDataContextWrapper>().As<IDatabaseFactory>().InstancePerLifetimeScope();
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628894
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaIModelDataContext не реализован, да и как его реализовать понятия не имею.

не обязательно интерфейс. можете класс зарегистрировать, без IModelDataContext.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628897
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaА если вот так сделать

Код: c#
1.
builder.RegisterType<ModelDataContextWrapper>().As<IDatabaseFactory>().InstancePerLifetimeScope();



да, можно и так. в зависимости от того, что вам от него нужно.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628898
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Нужен сам контекст
Код: c#
1.
2.
3.
4.
public ModelDataContextWrapper Get()
        {
            return _entityContext ?? (_entityContext = new ModelDataContextWrapper());
        }



Чтобы потом его убрать из DataManager и использовать, как вы описали
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628902
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaА сам DataManager это менеджер репозиторий с lazy инициализацией.

Lazy-инициализация:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class Some {

   public Some(Lazy<IMyService> service)
   {
       _service = service;
   }

   public void Method()
   {
      _service.Value.ServiceMethod();  //  <----- вот здесь создаётся/извлекается экземпляр IMyService
   }
}
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628906
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhahVostt,

Нужен сам контекст
Код: c#
1.
2.
3.
4.
public ModelDataContextWrapper Get()
        {
            return _entityContext ?? (_entityContext = new ModelDataContextWrapper());
        }




Чтобы потом его убрать из DataManager и использовать, как вы описали

Код: c#
1.
builder.RegisterType<ModelDataContextWrapper>().InstancePerLifetimeScope();



если для ASP.NET MVC вы используете интеграцию Autofac.Mvc, то InstancePerLifetimeScope означает время жизни HttpContext.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628907
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Тогда получается все в конструкторе указывать, все репозитории?
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628918
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhahVostt,

Тогда получается все в конструкторе указывать, все репозитории?

все, которые нужны , если где-то нужны вообще все, значит что-то не так с архитектурой. но если их слишком много, тогда можно обойтись публичными попертями в Lazy-обёртке.
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628921
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если я все правильно понял, то принцип такой:

Код: 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.
 private static void ConfigureIoC()
        {
            var builder = new ContainerBuilder();
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            builder.RegisterType<ModelDataContextWrapper>().InstancePerLifetimeScope();
            builder.RegisterType<DataManager>().As<IDataManager>().InstancePerHttpRequest();
            builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerHttpRequest();

            IContainer container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
        }

        public class DataManager : IDataManager
	{		
                public DataManager(IUserRepository repository)
		{
                        _userRepository = repository;
		}

        private IUserRepository _userRepository;
 }

        public class UserController : Controller
	{
		private IDataManager _dataManager;

        public UserController(IDataManager DataManager)
		{
            _dataManager = DataManager;
		}
}
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628933
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaЕсли я все правильно понял, то принцип такой:

да, всё верно, в этом и смысл
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628943
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Тогда есть несколько вопрос по вашим
Вы сказали:
все, которые нужны, если где-то нужны вообще все, значит что-то не так с архитектурой. но если их слишком много, тогда можно обойтись публичными попертями в Lazy-обёртке.


Как тогда поступить с классом DataManager, если это класс есть простое хранилище всех репозиторий
И ссылка на него передается в фабрике:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
internal class ControllerFactory: DefaultControllerFactory
	{
		protected override IController GetControllerInstance(System.Web.Routing.RequestContext RequestContext, Type ControllerType)
		{
			if (ControllerType == null) return null;

			return Activator.CreateInstance(ControllerType, new DataManager()) as Controller;
		}
	}



Неправильная архитектура? Т.к. в конструкторе придется передавать все репозитории.
Где я ошибся? Явно что-то не так

Потому что в контроллере дальше идет такие вещи типа:
Код: c#
1.
			var users = _dataManager.Users.GetUsers((int)user.ProviderUserKey);
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38628967
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PavluhaКак тогда поступить с классом DataManager, если это класс есть простое хранилище всех репозиторий

у вас уже есть DI (который Autofac), который является хранилищем всех репозиторий. зачем вам ещё один, свой? единственный полезный метод SaveChanges стоит вынести в отдельный интерфейс типа IUnitOfWork, и использовать его там, где требуется сохранение информации.


PavluhaПотому что в контроллере дальше идет такие вещи типа:
Код: c#
1.
			var users = _dataManager.Users.GetUsers((int)user.ProviderUserKey);



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

если же у вас контроллер, которому нужны все репозитории, то наверное это не очень хороший контроллер, может его разделить на несколько?
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38629005
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Но тогда получается надо абстрагироваться от определенных репозиторий и передавать, например, IRepository, и уже в контроллере приводить его к типу IUserRepository.

И тогда класс DataManager вообще не нужен. (Есть контроллеры, в которых необходим доступ к др репозитории, что ограничивает фабрику контроллеров)
...
Рейтинг: 0 / 0
IoC. Постепенный перевод проекта. Возможно ли
    #38629014
Pavluha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Почему я ввязался в IoC. Стали возникать потребности в поддержке других СУБД, вот я и решил переписать DAL.
Т.е. таким способом, если возникнет вопрос о реализации поддержки другой СУБД, то достаточно написать другой DAL для той СУБД, а все остальное вообще не изменится.

Правильный ли данный подход или надо было не городить огород, а просто использовать абстрактную фабрику и все?
...
Рейтинг: 0 / 0
25 сообщений из 47, страница 1 из 2
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / IoC. Постепенный перевод проекта. Возможно ли
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]