2011-09-23 14 views
6

Czy istnieje inny sposób deklarowania mojego ProductController dla rejestratora, który jest wtryskiwany?Jak wywnioskować typ obiektu i użyć tego typu w parametrze generycznym podczas budowy

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

Dziękuję Stephen

+0

Właściwa w jaki sposób? –

+2

Wnioskowanie wymaga użycia otwartego generycznego. Nie ma żadnych w tym przykładzie. – JaredPar

+0

Zgaduję, że mogę edytować tytuł i pytanie nieco. –

Odpowiedz

2

Wnioskowanie wymaga użycia otwartego generycznego. Nie ma żadnych w tej próbce.

0

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.

+0

Należy również zauważyć, że to dość łatwy krok od tego, co stworzyłem do posiadania ogólnej abstrakcyjnej fabryki lub metody fabryki do stworzenia. Gdyby to była moja implementacja, nie robiłbym tego tak, jak robiłem to w "DoSomething()" - na przykład. –

Powiązane problemy