How to derive an object type and use this type in a general parameter during construction

Is there any other way to declare my ProductController for the registrar that is being introduced?

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

Thanks Steven

+6
source share
2 answers

Conclusion requires the use of an open common. In this example, there are no

+2
source

If I'm not mistaken, what you want to do (wishing you could do) looks something like this:

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

I think you can get a pretty flexible interface if you digress a bit from your design. Here you have three parts: the controller, the registrar, and the controller and registrar object, which I will call the data transfer object. So, you have a "product controller" and a "product registrar" (which you are currently calling the "product controller registrar").

Say you have this structure of DTO objects:

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

Now, instead of writing a log about yourself with the controllers, why not have a logger and controller, both belong to the DTO? So, the logger looks 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 the 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>(); } } 

Now you have a log that will work on any DTO controller and a controller that will work on any DTO, and this controller will take as a constructor parameter a registrar that will work on the same DTO as it is. 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 connect them specifically or in general, as you wish:

 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 whipped it on the fly, so this may not be optimal, but I'm just trying to convey a general idea. You cannot declare a class with the generic type itself (as far as I know), but you can have two interaction classes (controller and registrar) that work with the same generic type. That is, an IController can own an ILogger, and when you instantiate an IController, you force its logger to work on the same type.

0
source

Source: https://habr.com/ru/post/897942/


All Articles