Pregunta

Acabo de terminar el artículo de James Kovac sobre Inversión de control e inyección de dependencias y luego usé lo que aprendí para hacer mi propio ejemplo de IoC / DI a continuación.

Estoy bastante satisfecho con este ejemplo ya que:

  • satisface la verificabilidad aspecto de IoC, ya que crea una instancia de los Clientes al pasar tanto un Repositorio como un MockRepository
  • también el servicio de autorización está desacoplado , lo que le permitiría, por ejemplo, escriba otro servicio de autorizaciones con reglas diferentes, y luego podría intercambiarlas fácilmente en función de otras condiciones

Sin embargo, mirando hacia el progreso desde aquí, algunas cosas parecen extrañas:

  • Parece que no tengo un " contenedor " . ¿Mi clase de cliente " actúa como contenedor " en este sentido?
  • si tuviera que llevar esto a WPF, ¿dónde encajarían los Módulos (en términos de Prisma) en este ejemplo? (por ejemplo, ¿serían los Servicios de Autorización y Repositorio los módulos?)
  • si tuviera que portar esto a WPF, ¿dónde encajaría MVVM ? Tiene partes de MVVM a través de la inyección de dependencia o MVVM es algo completamente separado.

Gracias por cualquier dirección que puedas proporcionar sobre esto.

NUEVO CÓDIGO BASADO EN COMENTARIOS:

using System;
using System.Linq;
using System.Collections.Generic;

namespace TestSimpleDependencyInjection1
{
    class Program
    {
        static void Main(string[] args)
        {
            AuthorizationService authorizationService = new AuthorizationService();

            //real example
            Repository repository = new Repository(authorizationService);
            for (int id = 1; id <= 3; id++)
            {
                Customer customer = repository.GetCustomer(id);
                customer.Display();
            }
            Console.WriteLine();

            //mock test example
            MockRepository mockRepository = new MockRepository(authorizationService);
            Customer mockCustomerAdministrator = repository.GetCustomer(1);
            Customer mockCustomerSalesperson = repository.GetCustomer(2);
            UnitTester.Assert("Administrators have access", mockCustomerAdministrator.GetAuthorizationMessage(), "Access Granted");
            UnitTester.Assert("Salespeople do not have access", mockCustomerAdministrator.GetAuthorizationMessage(), "Access Granted");

            Console.ReadLine();
        }
    }

    public static class UnitTester
    {
        public static void Assert(string title, string value, string expectedResult)
        {
            Console.WriteLine(value == expectedResult ? String.Format("{0}: test succeeded", title) : String.Format("{0}: TEST FAILED!", title));
        }
    }

    public class Customer
    {

        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public AccessGroup AccessGroup { get; set; }
        public AuthorizationService AuthorizationService { get; set; }

        public string GetAuthorizationMessage()
        {
            return this.AuthorizationService.GetAccessMessage(this);
        }

        public Customer()
        {

        }

        public void Display()
        {
            Console.WriteLine("Customer: {1}, {0} ({2}): {3}", this.FirstName, this.LastName, this.AccessGroup, this.GetAuthorizationMessage());
        }
    }

    public class AuthorizationService
    {
        public string GetAccessMessage(Customer customer)
        {
            return customer.AccessGroup == AccessGroup.Administrator ? "Access Granted" : "Access Denied";
        }
    }


    public class Repository : IRepository
    {
        private List<Customer> _customerSet = new List<Customer>();
        private AuthorizationService _authorizationService;

        public Repository(AuthorizationService authorizationService)
        {
            _authorizationService = authorizationService;
            _customerSet.Add(new Customer {AuthorizationService = _authorizationService, ID = 1, FirstName = "Jim", LastName = "Smith", AccessGroup = AccessGroup.Administrator });
            _customerSet.Add(new Customer {AuthorizationService = _authorizationService, ID = 2, FirstName = "John", LastName = "Johnson", AccessGroup = AccessGroup.Administrator });
            _customerSet.Add(new Customer {AuthorizationService = _authorizationService, ID = 3, FirstName = "Hank", LastName = "Rivers", AccessGroup = AccessGroup.Salesperson });
        }

        public Customer GetCustomer(int id)
        {
            return (from c in _customerSet
                    where c.ID == id
                    select c).SingleOrDefault();
        }
    }

    public class MockRepository : IRepository
    {
        private List<Customer> _customerSet = new List<Customer>();
        private AuthorizationService _authorizationService;

        public MockRepository(AuthorizationService authorizationService)
        {
            _authorizationService = authorizationService;
            _customerSet.Add(new Customer { AuthorizationService = _authorizationService, ID = 1, FirstName = "Test1AdministratorFirstName", LastName = "Test1AdministratorLastName", AccessGroup = AccessGroup.Administrator });
            _customerSet.Add(new Customer { AuthorizationService = _authorizationService, ID = 2, FirstName = "Test2SalespersonFirstName", LastName = "Test2SalesPersonLastName", AccessGroup = AccessGroup.Salesperson });
        }

        public Customer GetCustomer(int id)
        {
            return (from c in _customerSet
                            where c.ID == id
                            select c).SingleOrDefault();
        }

    }

    public interface IRepository
    {
        Customer GetCustomer(int id);
    }

    public enum AccessGroup
    {
        Administrator,
        Salesperson
    }
}

Y POR SOLICITUD, AQUÍ ESTÁ EL CÓDIGO ORIGINAL:

using System;
using System.Collections.Generic;

namespace TestSimpleDependencyInjection1
{
    class Program
    {
        static void Main(string[] args)
        {
            AuthorizationService authorizationService = new AuthorizationService();

            //real example
            Repository repository = new Repository();
            for (int id = 1; id <= 3; id++)
            {
                Customer customer = new Customer(id, authorizationService, repository);
                customer.Display();
            }
            Console.WriteLine();

            //mock test example
            MockRepository mockRepository = new MockRepository();
            Customer mockCustomerAdministrator = new Customer(1, authorizationService, mockRepository);
            Customer mockCustomerSalesperson = new Customer(2, authorizationService, mockRepository);
            UnitTester.Assert("Administrators have access", mockCustomerAdministrator.GetAuthorizationMessage(), "Access Granted");
            UnitTester.Assert("Salespeople do not have access", mockCustomerAdministrator.GetAuthorizationMessage(), "Access Granted");

            Console.ReadLine();
        }
    }

    public static class UnitTester
    {
        public static void Assert(string title, string value, string expectedResult)
        {
            Console.WriteLine(value == expectedResult ? String.Format("{0}: test succeeded", title) : String.Format("{0}: TEST FAILED!", title));
        }
    }

    public class Customer
    {
        private AuthorizationService authorizationService;
        private IRepository repository;

        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public AccessGroup AccessGroup { get; set; }

        public string GetAuthorizationMessage()
        {
            return authorizationService.GetAccessMessage(this);
        }

        public Customer(int id, AuthorizationService authorizationService, IRepository repository)
        {
            this.authorizationService = authorizationService;
            this.repository = repository;

            CustomerDB customerDB = repository.GetCustomerDB(id);
            this.ID = customerDB.ID;
            this.FirstName = customerDB.FirstName;
            this.LastName = customerDB.LastName;
            this.AccessGroup = customerDB.AccessGroup;
        }

        public void Display()
        {
            Console.WriteLine("Customer: {1}, {0} ({2}): {3}", this.FirstName, this.LastName, this.AccessGroup, this.GetAuthorizationMessage());
        }
    }

    public class AuthorizationService
    {
        public string GetAccessMessage(Customer customer)
        {
            return customer.AccessGroup == AccessGroup.Administrator ? "Access Granted" : "Access Denied";
        }
    }


    public class Repository : IRepository
    {
        private List<CustomerDB> _customerDBSet = new List<CustomerDB>();

        public Repository()
        {
            _customerDBSet.Add(new CustomerDB { ID = 1, FirstName = "Jim", LastName = "Smith", AccessGroup = AccessGroup.Administrator });
            _customerDBSet.Add(new CustomerDB { ID = 2, FirstName = "John", LastName = "Johnson", AccessGroup = AccessGroup.Administrator });
            _customerDBSet.Add(new CustomerDB { ID = 3, FirstName = "Hank", LastName = "Rivers", AccessGroup = AccessGroup.Salesperson });
        }

        public CustomerDB GetCustomerDB(int id)
        {
            CustomerDB customerDBchosen = null;
            //this should be done with LINQ (couldn't get it CustomerDB to implement IEnumerable correctly)
            foreach (CustomerDB customerDB in _customerDBSet)
            {
                if (customerDB.ID == id)
                {
                    customerDBchosen = customerDB;
                    break;
                }
            }
            return customerDBchosen;
        }
    }

    public class MockRepository : IRepository
    {
        public CustomerDB GetCustomerDB(int id)
        {
            switch (id)
            {
                case 1:
                    return new CustomerDB { ID = 1, FirstName = "Test1AdministratorFirstName", LastName = "Test1AdministratorLastName", AccessGroup = AccessGroup.Administrator };
                case 2:
                    return new CustomerDB { ID = 2, FirstName = "Test2SalespersonFirstName", LastName = "Test2SalesPersonLastName", AccessGroup = AccessGroup.Salesperson };
                default:
                    return null;
            }
        }
    }

    public interface IRepository
    {
        CustomerDB GetCustomerDB(int id);
    }

    public class CustomerDB
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public AccessGroup AccessGroup { get; set; }
    }

    public enum AccessGroup
    {
        Administrator,
        Salesperson
    }
}
¿Fue útil?

Solución

Su código viola el principio de responsabilidad única de una manera bastante seria.

http://en.wikipedia.org/wiki/Single_responsibility_principle

El objeto de su Cliente no debe cargarse desde un repositorio, el repositorio debe estar cargando el objeto de Cliente y devolvérselo a la persona que llama.

Esperaría algo más como:

Customer customer = repository.GetCustomer(3);

Otros consejos

el uso de las declaraciones Switch en la mayoría de los casos viola el SRP. compruebe esto para conocer las formas de eliminar las declaraciones de cambio en su código. El desafío & amp; La belleza de escribir un código débilmente acoplado es eliminar si, en caso contrario, & amp; cambiar declaraciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top