Jeśli się nie mylę, to, czego szukasz, aby zrobić (chcąc nie można zrobić) jest coś takiego jak:
class ProductController<T> : Controller where T : ProductController
{
ILogger<T> _logger;
... etc
}
myślę, że możesz uzyskać dość elastyczny interfejs, jeśli odsuniesz trochę od swojego projektu. Masz tu trzy części - kontroler, rejestrator i obiekt kontrolera i rejestratora, który nazwiemy obiektem przesyłania danych. Masz więc "kontroler produktu" i "rejestrator produktu" (który obecnie nazywasz "rejestratorem kontrolera produktu").
Powiedzmy, że masz ten DTO obiektu strukturę:
public class DataTransferBase { /*This is what both logger and controller operate on*/ }
public class Product : DataTransferBase { }
Teraz, zamiast rejestratora dotyczącej się z kontrolerami, dlaczego nie ma rejestratora i sterowania zarówno zajmować się DTOs? Rejestrator jest tak jak:
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 */ }
}
... i regulator jest tak:
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>();
}
}
Co masz tu teraz jest rejestrator, który będzie działać na dowolnym DTO oraz sterownik, który będzie działać na dowolnym DTO i ten kontroler bierze się za parametr konstruktora, rejestrator, który będzie działał na tym samym DTO, co robi. Teraz można mieć bardziej konkretne implementacje jeśli chcesz:
public class ProductFileLogger : FileLogger<Product>
{
public override void Log(Product item) { /* Get all specific with item */}
}
i
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>();
}
}
I, można podłączyć je jako konkretnie lub ogólnie jak należy:
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
}
}
proszę Zwróćcie uwagę, że po prostu ułożyłem to w locie, więc może nie być optymalne, ale próbuję przekazać ogólny pomysł. Nie możesz zadeklarować klasy o typie ogólnym (o ile wiem), ale możesz mieć dwie klasy interakcji (kontroler i rejestrator), które działają na tym samym typie ogólnym. Oznacza to, że IController może posiadać ILogger i kiedy tworzysz instancję IController, zmuszasz jego program do działania na tym samym typie.
Właściwa w jaki sposób? –
Wnioskowanie wymaga użycia otwartego generycznego. Nie ma żadnych w tym przykładzie. – JaredPar
Zgaduję, że mogę edytować tytuł i pytanie nieco. –