проблемы с di с использованием castle windsor

#c# #dependency-injection #castle-windsor

#c# #внедрение зависимостей #castle-windsor

Вопрос:

Я пытаюсь изучить di с использованием windsor и сталкиваюсь с проблемами. У меня есть существующий DAL, который я использую, и я хотел бы использовать di с этим dal. У меня есть следующий интерфейс (упрощенный ради этого поста) —

 public interface IConnection 
    {
        void OpenConnection(string ConnectionStringName);
        void CloseConnection();
        DbDataReader ExecuteReader(string query);
    }
  

и реализация —

 public class Connection : IConnection
    {
        private DBManager manager = new DBManager();

        public void OpenConnection(string ConnectionStringName)
        {
            manager.OpenConnection("connectionstringname");
        }

        public void CloseConnection()
        {
            manager.CloseConnection();
        }

        public DbDataReader ExecuteReader(string query)
        {
            return manager.ExecuteReader(query, CommandType.Text);
        }
    }
  

Вот мой установщик windsor —

 public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Component.For<IConnection>().ImplementedBy<Connection>()
                .LifeStyle.Transient
                );
        }
  

и вот где я делаю инъекцию —

 public class GetData
    {
        private IConnection conn;

        public GetData()
        {
        }

        public GetData(IConnection conn)
        {
            this.conn = conn;
        }

        public List<Entity> GetAllData()
        {
            List<Entity> data= new List<Entity>();
            //IConnection conn = new Connection();
            conn.OpenConnection("connectionstringname");

            try
            {
                var r = conn.ExecuteReader("select ... from ...");
                //code to convert reader to data list
                r.Dispose();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                conn.CloseConnection();
            }

            return data;            
        }
    }
  

внедрение не работает. Если я выполняю пошаговый код, conn всегда равен нулю в GetAllData.
когда я выполняю установку, появляется зависимость IConnection / Connection, и в ней говорится, что все требуемые зависимости могут быть разрешены.

Кто-нибудь может увидеть что-нибудь, что я делаю неправильно? Как я уже сказал, я новичок в di, поэтому, если я использую его неправильно, пожалуйста, дайте мне знать.

Спасибо

РЕДАКТИРОВАТЬ — Я не совсем уверен, что понимаю. Если я изменю свой установщик на следующий, он по-прежнему не будет работать —

 container.Register(
                Component.For<IConnection>().ImplementedBy<Connection>()
                .LifeStyle.Transient
                );

            container.Register(
                Component.For<GetData>()
                );

            container.Resolve<GetData>();
  

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

Комментарии:

1. где бы мне зарегистрировать getData?

2. Вам нужно зарегистрироваться GetData в контейнере, затем разрешить его из контейнера. Если вы просто сделаете new GetData() , контейнер ничего не сможет впрыснуть.

3. Маурисио — спасибо за помощь, но я все еще не понимаю. пожалуйста, посмотрите правки выше — двигаюсь ли я в правильном направлении?

4. @czuroski: да, выглядит нормально. Можете ли вы опубликовать полный тестовый пример, чтобы я мог точно определить вашу проблему?

5. @Mauricio — У меня не написано ни одного тестового примера…. Я еще не пытался написать ни одного, поскольку не был уверен, как с ними справиться.

Ответ №1:

Не уверен, и я могу ошибаться, но я не заметил, чтобы вы вызывали

 container.Resolve
  

Если вы работали с ASP.NET MVC, вы можете заставить это работать автоматически с помощью внедрения контроллера, но вам все равно нужно будет подключить интерфейс к какому-то заводскому методу. В вашем примере я бы добавил

 public class GetData
{
    private IConnection conn = ContainerManager.Instance.Resolve<IConnection>();
    //where ContainerManager.Instance points to the container instance
    ...
}
  

Комментарии:

1. Я использую MVC, и у меня работает внедрение контроллера. было бы лучше вызвать container.resolve, где вы сказали, или в моем WindsorControllerFactory?

2. @czuroski о, я понимаю. Я не думаю, что вы можете использовать ASP.NET Внедрение MVC для чего угодно, кроме внедрения контроллера , поэтому я думаю (может быть, это неверно), вы не можете использовать это, потому что ASP.NET имеет встроенные фабрики, которые подключаются автоматически за сценой. В своих проектах я создаю базовый класс, который содержит всю Resolve логику, и наследую типы из этой базы.

Ответ №2:

вы вызывали install ()? например:

 container.Install(Castle.Windsor.Installer.Configuration.FromAppConfig());