繁体   English   中英

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

[英]How to infer the type of an object and use that type in a generic parameter during construction

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

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

假设你有这个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时,您可以强制其记录器以相同的类型运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM