Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If I'm not mistaken, what you're looking to do (wishing you could do) is something like:</p> <pre><code>class ProductController&lt;T&gt; : Controller where T : ProductController { ILogger&lt;T&gt; _logger; ... etc } </code></pre> <p>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").</p> <p>Let's say that you have this DTO object structure:</p> <pre><code>public class DataTransferBase { /*This is what both logger and controller operate on*/ } public class Product : DataTransferBase { } </code></pre> <p>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:</p> <pre><code>public interface ILogger { void Log(string message); } public interface ILogger&lt;T&gt; : ILogger where T : DataTransferBase { void Log(T item); } public class FileLogger&lt;T&gt; : ILogger&lt;T&gt; 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 */ } } </code></pre> <p>... and controller is like:</p> <pre><code>public interface IController&lt;T&gt; where T : DataTransferBase {} public class Controller&lt;T&gt; : IController&lt;T&gt; where T : DataTransferBase { /// &lt;summary&gt;Initializes a new instance of the ProductController class.&lt;/summary&gt; public Controller(ILogger&lt;T&gt; logger) { } public virtual List&lt;T&gt; GetItems() { return new List&lt;T&gt;(); } } </code></pre> <p>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:</p> <pre><code>public class ProductFileLogger : FileLogger&lt;Product&gt; { public override void Log(Product item) { /* Get all specific with item */} } </code></pre> <p>and</p> <pre><code>public class ProductController : Controller&lt;Product&gt; { /// &lt;summary&gt; /// Initializes a new instance of the ProductController class. /// &lt;/summary&gt; public ProductController(ILogger&lt;Product&gt; productLogger) : base(productLogger) { } public override List&lt;Product&gt; GetItems() { return new List&lt;Product&gt;(); } } </code></pre> <p>And, you can wire these up as specifically or generally as you please:</p> <pre><code>public class Client { private void DoSomething() { IController&lt;Product&gt; myController = new ProductController(new ProductFileLogger()); //If you want to be specific IController&lt;Product&gt; myController2 = new Controller&lt;Product&gt;(new ProductFileLogger()); //If you want a generic controller and specific logger IController&lt;Product&gt; myController3 = new Controller&lt;Product&gt;(new FileLogger&lt;Product&gt;()); //If you want to be as generic as possible } } </code></pre> <p>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.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload