2011-09-23 49 views
6

是否有另一种方法来为注入的记录器声明我的ProductController?如何推断对象的类型并在构造过程中在通用参数中使用该类型

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; 
    } 
{ 

谢谢 斯蒂芬

+0

适当以什么方式? –

+2

推理要求使用开放通用。有没有在这个样本 – JaredPar

+0

猜猜我可能编辑标题和问题 –

回答

2

推理要求使用开放通用。此示例中没有任何内容

0

如果我没有记错的话,你希望做的(希望你可以做)什么是一样的东西:

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

我认为,如果您从设计中拉回一点,您可以获得相当灵活的界面。这里有三部分 - 控制器,记录器和控制器和记录器的对象,我将称其为数据传输对象。所以,你有“产品控制器”和“产品记录器”(你现在称之为“产品控制器记录器”)。

比方说,你有这样的DTO对象结构:

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

public class Product : DataTransferBase { } 

现在,而不是与控制器有关自身记录,为什么不把记录器和控制器都关心自己与DTO的?所以记录是这样的:

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 */ } 
} 

...和控制器是这样的:

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>(); 
    } 
} 

你现在在这里什么是可以在任何DTO操作记录器和控制器,可以在任何DTO操作,并且该控制器恰好将构造参数作为构造函数参数使用,该记录器将在与之相同的DTO上运行。现在,你可以有更具体的实施方案,如果你想:

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

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>(); 
    } 
} 

而且,您可以具体或一般请电汇这些,作为你:

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 
    } 
} 

请请注意,我只是简单地将这件事情匆匆掠过,所以它可能不是最佳的,但我只是想传达一般想法。你不能用自己的泛型类声明一个类(据我所知),但是你可以有两个相互作用的类(控制器和记录器)在相同的泛型类型上操作。也就是说,IController可以拥有一个ILogger,当你实例化IController时,你可以强制其记录器在相同的类型上运行。

+0

我也应该注意到,从创建到创建一个通用的抽象工厂或工厂方法是一个非常简单的步骤。如果这是我的实现,那么我实际上不会按照我在“DoSomething()”中所做的方式来连接这些东西 - 例如。 –