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

发布于 2024-12-06 09:17:25 字数 493 浏览 0 评论 0原文

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

谢谢你, 斯蒂芬

Is there another way of declaring my ProductController for the logger that is being injected?

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

Thank you,
Stephen

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我也只是我 2024-12-13 09:17:25

推理需要使用开放泛型。此样本中没有

Inference requires the use of an open generic. There are none in this sample

你怎么敢 2024-12-13 09:17:25

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

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 时,您可以强制其记录器对相同类型进行操作。

If I'm not mistaken, what you're looking to do (wishing you could do) is something like:

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

I think that you can get a fairly flexible interface if you pull back a little from your design. You have three parts here -- a controller, a logger, and the object of the controller and logger, which I'll call a data transfer object. So, you have "controller of product" and "logger of product" (which you're currently calling "logger of controller of product").

Let's say that you have this DTO object structure:

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

public class Product : DataTransferBase { }

Now, instead of the logger concerning itself with controllers, why not have the logger and controller both concern themselves with DTOs? So logger is like:

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

... and controller is like:

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

What you have here now is a logger that will operate on any DTO and a controller that will operate on any DTO, and that controller happens to take as a constructor parameter, a logger that will operate on the same DTO that it does. Now, you can have more specific implementations if you want:

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

and

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

And, you can wire these up as specifically or generally as you please:

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

Please note, that I just kind of whipped this up on the fly, so it may not be optimal, but I'm just trying to convey the general idea. You can't declare a class with a generic type of itself (as far as I know), but you can have two classes interact (controller and logger) that operate on the same generic type. That is, IController can own an ILogger and when you instantiate IController, you force its logger to operate on the same type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文