2011-09-23 14 views
6

¿Hay alguna otra manera de declarar mi ProductController para el registrador que se está inyectando?Cómo inferir el tipo de un objeto y usar ese tipo en un parámetro genérico durante la construcción

public class ProductController : Controller 
{ 
    private readonly LoggingInterface.ILogger<ProductController> _logger; 
    private readonly IProductRepository _productRepository; 

    public ProductController(LoggingInterface.ILogger<ProductController> logger, IProductRepository productRepository) 
    { 
     _logger = logger; 
     _productRepository = productRepository; 
    } 
{ 

Gracias, Stephen

+0

¿Correcto de qué manera? –

+2

Inferencia requiere el uso de un genérico abierto. No hay ninguno en esta muestra – JaredPar

+0

Supongo que podría editar el título y preguntar un poco –

Respuesta

2

Inference requiere el uso de un genérico abierto. No hay ninguno en esta muestra

0

Si no me equivoco, lo que busca hacer (deseando poder hacerlo) es algo así como:

class ProductController<T> : Controller where T : ProductController 
{ 
    ILogger<T> _logger; 
    ... etc 
} 

creo que puede obtener una interfaz bastante flexible si se aleja un poco de su diseño. Aquí tiene tres partes: un controlador, un registrador y el objeto del controlador y el registrador, que llamaré un objeto de transferencia de datos. Entonces, tiene "controlador de producto" y "registrador de producto" (que actualmente llama "registrador de controlador de producto").

Digamos que usted tiene esta estructura de objetos DTO:

public class DataTransferBase { /*This is what both logger and controller operate on*/ } 

public class Product : DataTransferBase { } 

Ahora, en lugar del registrador en relación con los controladores en sí, ¿por qué no tiene el registrador y el controlador tanto a sí mismos preocupación por dtos? Así es como registrador:

public interface ILogger 
{ 
    void Log(string message); 
} 

public interface ILogger<T> : ILogger where T : DataTransferBase 
{ 
    void Log(T item); 
} 

public class FileLogger<T> : ILogger<T> where T : DataTransferBase 
{ 
    public virtual void Log(T item) { /* Write item.ToString() to a file or something */ } 
    public void Log(string message) { /* Write the string to a file */ } 
} 

... y el controlador es como:

public interface IController<T> where T : DataTransferBase {} 

public class Controller<T> : IController<T> where T : DataTransferBase 
{ 
    /// <summary>Initializes a new instance of the ProductController class.</summary> 
    public Controller(ILogger<T> logger) 
    { 

    } 

    public virtual List<T> GetItems() 
    { 
     return new List<T>(); 
    } 
} 

Lo que tenemos aquí ahora es un registrador que operará en cualquier DTO y un controlador que operará en cualquier DTO , y ese controlador pasa a tomar como parámetro constructor, un registrador que operará en el mismo DTO que lo hace. Ahora, usted puede tener implementaciones más específicas si se quiere:

public class ProductFileLogger : FileLogger<Product> 
{ 
    public override void Log(Product item) { /* Get all specific with item */} 
} 

y

public class ProductController : Controller<Product> 
{ 
    /// <summary> 
    /// Initializes a new instance of the ProductController class. 
    /// </summary> 
    public ProductController(ILogger<Product> productLogger) : base(productLogger) { } 

    public override List<Product> GetItems() 
    { 
     return new List<Product>(); 
    } 
} 

Y, se puede conectar éstos como términos generales o específicos a su gusto:

public class Client 
{ 
    private void DoSomething() 
    { 
     IController<Product> myController = new ProductController(new ProductFileLogger()); //If you want to be specific 
     IController<Product> myController2 = new Controller<Product>(new ProductFileLogger()); //If you want a generic controller and specific logger 
     IController<Product> myController3 = new Controller<Product>(new FileLogger<Product>()); //If you want to be as generic as possible 
    } 
} 

favor tenga en cuenta que, simplemente, como que lo preparé sobre la marcha, por lo que puede no ser óptimo, pero estoy tratando de transmitir la idea general. No se puede declarar una clase con un tipo genérico de sí mismo (hasta donde sé), pero puede tener dos clases interactuando (controlador y registrador) que operan en el mismo tipo genérico. Es decir, IController puede ser propietario de un ILogger y cuando crea una instancia de IController, fuerza a su registrador a operar del mismo tipo.

+0

También debería tener en cuenta que es un paso bastante fácil de lo que creé a tener una fábrica abstracta genérica o método de fábrica para la creación. Si esta fuera mi implementación, en realidad no estaría conectando esas cosas de la manera en que lo hice en "DoSomething()" - eso fue solo por ejemplo. –

Cuestiones relacionadas