Pregunta

Soy un novato cuando se trata de DI y ninject y yo estoy luchando un poco acerca de cuándo la inyección real debería suceder y cómo iniciar el vinculante.

Lo estoy usando ya en mi aplicación web y que funcione bien allí, pero ahora quiero usar la inyección en una biblioteca de clases.

Decir que tengo una clase como esta:

public class TestClass
{
    [Inject]
    public IRoleRepository RoleRepository { get; set; }
    [Inject]
    public ISiteRepository SiteRepository { get; set; }
    [Inject]
    public IUserRepository UserRepository { get; set; }

    private readonly string _fileName;

    public TestClass(string fileName)
    {
        _fileName = fileName;
    }

    public void ImportData()
    {
        var user = UserRepository.GetByUserName("myname");
        var role = RoleRepository.GetByRoleName("myname");
        var site = SiteRepository.GetByID(15);
        // Use file etc
    }

}

Quiero usar la inyección propiedad aquí porque tengo que pasar en una nombre de archivo en mi constructor. Estoy en lo correcto al decir que si necesito pasar de un parámetro de constructor, no puedo usar la inyección de constructor? Si puedo usar la inyección de constructor con parámetros adicionales, ¿cómo Paso esos parámetros en?

Tengo una aplicación de consola que consume por clase de prueba que se ve tan siguiente:

class Program
{
    static void Main(string[] args)
    {
        // NinjectRepositoryModule Binds my IRoleRepository etc to concrete
        // types and works fine as I'm using it in my web app without any
        // problems
        IKernel kernel = new StandardKernel(new NinjectRepositoryModule());

        var test = new TestClass("filename");

        test.ImportData();
    }
}

Mi problema es que cuando llamo test.ImportData() mis repositorios son nulos - nada se ha inyectado en ellos. He intentado crear otro módulo y llamar

Bind<TestClass>().ToSelf();

como pensé que esto podría resolver todas las propiedades de inyección en TestClass pero estoy llegando a ninguna parte.

Estoy seguro de que este es un problema trivial, pero me parece que no puede averiguar cómo ir sobre esto.

¿Fue útil?

Solución

Usted es TestClass directamente Newing, que Ninject no tiene manera de interceptar - recuerde que no hay magia como la transformación de código interceptando sus news etc

.

Se debe hacer kernel.Get<TestClass> lugar.

De no ser así, puede inyectarse después de new con un kernel.Inject( test);

Creo que hay un artículo en el wiki que habla de Inject vs Get etc.

Tenga en cuenta que en Get, o Inject llamadas directas generales están hacien un olor incorrecto del servicio de localización, que es un anti patrón. En el caso de su aplicación web, el NinjectHttpModule y PageBase son el gancho que intercepta la creación de objetos -. Similares existen interceptores / lugares lógicos para interceptar en otros estilos de la aplicación

Re su Bind<TestClass>().ToSelf(), generalmente un StandardKernel tiene ImplicitSelfBinding = true lo que haría innecesario que (a menos que quiera influir en su alcance a ser algo más que .InTransientScope()).

Un punto final de estilo: - que está utilizando la inyección propiedad. Rara vez hay buenas razones para ello, por lo que deben usar la inyección de constructor en su lugar.

Y no ir a comprar inyección de dependencias en .NET @ Marcos Seemann , que tiene montones de excelentes mensajes por aquí, que cubren una gran cantidad de consideraciones importantes pero sutiles en y alrededor del área de inyección de dependencia.

Otros consejos

Aceptar

He encontrado la manera de hacer lo que necesito, gracias en parte a sus comentarios Ruben. He creado un nuevo módulo que básicamente contiene la configuración que yo uso en la biblioteca de clases. Dentro de este módulo, ya sea que puedo enlazar mediante una interfaz de marcador de posición o puedo agregar un parámetro de constructor para el CustomerLoader. A continuación se muestra el código de una aplicación de consola ficticio para demostrar en ambos sentidos.

Esto podría ayudar a alguien más para empezar con Ninject!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject.Core;
using Ninject.Core.Behavior;

namespace NinjectTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var kernel = new StandardKernel(new RepositoryModule(), new  ProgramModule());            
            var loader = kernel.Get<CustomerLoader>();
            loader.LoadCustomer();
            Console.ReadKey();
        }
    }

    public class ProgramModule : StandardModule
    {
        public override void Load()
        {
            // To get ninject to add the constructor parameter uncomment the line below
            //Bind<CustomerLoader>().ToSelf().WithArgument("fileName", "string argument file name");
            Bind<LiveFileName>().To<LiveFileName>();
        }
    }

    public class RepositoryModule : StandardModule
    {
        public override void Load()
        {
            Bind<ICustomerRepository>().To<CustomerRepository>().Using<SingletonBehavior>();
        }
    }

    public interface IFileNameContainer
    {
        string FileName { get; }
    }
    public class LiveFileName : IFileNameContainer
    {
        public string FileName
        {
            get { return "live file name"; }
        }
    }


    public class CustomerLoader
    {
        [Inject]
        public ICustomerRepository CustomerRepository { get; set; }
        private string _fileName;

        // To get ninject to add the constructor parameter uncomment the line below
        //public CustomerLoader(string fileName)
        //{
        //    _fileName = fileName;
        //}
        public CustomerLoader(IFileNameContainer fileNameContainer)
        {
            _fileName = fileNameContainer.FileName;
        }

        public void LoadCustomer()
        {
            Customer c = CustomerRepository.GetCustomer();
            Console.WriteLine(string.Format("Name:{0}\nAge:{1}\nFile name is:{2}", c.Name, c.Age, _fileName));
        }
    }

    public interface ICustomerRepository
    {
        Customer GetCustomer();
    }
    public class CustomerRepository : ICustomerRepository
    {
        public Customer GetCustomer()
        {
            return new Customer() { Name = "Ciaran", Age = 29 };
        }
    }
    public class Customer
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top