如何推断对象的类型并在构造期间在泛型参数中使用该类型

本文关键字:类型 参数 泛型 对象 何推断 | 更新日期: 2023-09-27 18:09:27

是否有另一种方式为正在注入的记录器声明我的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;
    }
{

谢谢你,斯蒂芬。

如何推断对象的类型并在构造期间在泛型参数中使用该类型

推断需要使用开放泛型。在这个示例中没有

如果我没弄错的话,你想做的(希望你能做的)是这样的:

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

我认为你可以得到一个相当灵活的界面,如果你从你的设计撤回一点。这里有三个部分,一个控制器,一个记录器,以及控制器和记录器的对象,我称之为数据传输对象。所以,你有"controller of product"answers"logger of product"(你现在称之为"logger of controller of product")。

假设你有这样的DTO对象结构:
public class DataTransferBase { /*This is what both logger and controller operate on*/ }
public class Product : DataTransferBase { }

现在,与其让记录器自己关心控制器,为什么不让记录器和控制器都关心dto呢?所以logger就像:

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时,你可以强制它的logger在相同的类型上运行。