Note that there are some explanatory texts on larger screens.

plurals
  1. POdesign for interchangeable use of lightweight and full objects
    primarykey
    data
    text
    <p>I am working in a system that uses an interface and class structure similar to this:</p> <pre><code>interface ILw // a lightweight interface definition class Medium : ILw class FullA : Medium // full class definitions class FullB : Medium class LwA : ILw // lightweight class definitions class LwB : ILw </code></pre> <p>Within the system I encounter objects that could be full or lightweight, and so have functions that expect the <em>ILw</em> interface. The problem I run into with this design is that there are more data and methods that need to be shared between the full and lightweight versions of the objects than is defined in <em>ILw</em>. So I find myself needing to do something like this:</p> <pre><code>if (myvar is FullA) { (myvar as FullA).MyFunction() } else { (myvar as LwA).MyFunction() } </code></pre> <p>where <em>MyFunction()</em> is implemented separately in each <em>FullA</em> and <em>LwA</em> and may work on identical data structures. I want to eliminate this code duplication.</p> <p>With my C++ background it seems to be a typical case for multiple inheritance; i.e., define a class <em>SharedA</em> for the data and methods that both need and add it to the parent list of <em>FullA</em> and <em>LwA</em>. But I need some guidance to help think through this in a C# and interfaces world. Is there an accepted pattern to solve this problem?</p> <p>Thank you. </p> <p><strong>UPDATE:</strong></p> <p>With the help of the comments received so far, I've been able to refactor for a better design with 1) an intermediate interface requiring an aggregate for shared data and 2) an extension class for methods to work on this data. Ideally these (data and methods) would be joined in the same construct. I feel like mate-in-1 is on the board and I just don't see it.</p> <pre><code>public interface ILwBase { } class Medium : ILwBase { } public class LwDataA { static private int _count = 0; public int id; public LwDataA() { id = ++_count; } } public interface ILwA : ILwBase { LwDataA ExtData { get; } } public static class ExtLwA { public static void MyFunction(this ILwA o) { Console.WriteLine("id = " + o.ExtData.id); } } class LwA : ILwA { private LwDataA _extData = new LwDataA(); public LwDataA ExtData { get { return (_extData); } } } class FullA : Medium, ILwA { private LwDataA _extData = new LwDataA(); public LwDataA ExtData { get { return (_extData); } } } class Program { static void Main() { ILwA a1 = new FullA(); ILwA a2 = new LwA(); a1.MyFunction(); a2.MyFunction(); } } </code></pre> <p>This allows what I need with only two lines of duplicate code between LwA and FullA. And it removes the need to call through an aggregate property (my previous edit) or implement wrappers around an aggregate. </p> <p>Hopefully this clarifies what I am trying to achieve. Is this the best solution?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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