2

I have a scenario. I am trying to wrap my code up so that I have generic entities which instantiate themselves according to the realm that they are in.

Like an onion which only has a layer which it deals with itself but at the same time allowing somebody from a higher level to trigger the internal layers to start doing something. It allows me to package my components in a nicer and more reusable manner since i will be able to implement code which propagates safely to all required modules without affecting higher levels which may be deriving from the same base classes. So basically there will be a hierarchy of levels which classes will share commonality.

In short, I have a property of type interface(IBar) inside an interface(IFoo) which is inheriting another interface(IFooBase), and i have another property inside this base interface which is the same name of the property from interface above of a type which is a base interface of its original(IBarBase)

My problem is my implementation of Foo, which calls a method from FooBase which accesses property of IBar cannot access IBarBase because the object is not instantiated, the reason being that inherited interfaces of the same time performs hiding of properties instead of overwriting.

Any advice will be greatly appreciated on how i can go about assigning IBarBase with an instantiated object of Bar (of which is actually an implementation of IBar and derived from IBarBase) so that i may be able to access the property from a lower level to perform some task.

Sorry is this sounding too complex? im not sure if i am making any sense, the code before is for reference. And a picture also for illustration

enter image description here

public interface IFoo : IFooBase
{
    new IBar inst { get; set; }
}

public interface IFooBase
{
    IBarBase inst { get; set; }
    void SetEventHandlers();
}

public interface IBar : IBarBase
{
    int stuff { get; set; }
}

public interface IBarBase
{
    int otherStuff { get; set;}
}

public class Foo : FooBase, IFoo
{
    public Foo()
    {
        inst = new Bar();
        SetEventHandler();
    }

    public new IBar inst { get; set; }
}

public class FooBase : IFooBase
{
    public void SetEventHandler()
    {
        inst.otherStuff = 123;
    }

    public IBarBase inst { get; set; }
}

public class Bar : BarBase, IBar
{
    public int stuff { get; set; }
}

public class BarBase : 
{
    public int otherStuff { get; set;}
}
stuartd
  • 70,509
  • 14
  • 132
  • 163
CJC
  • 795
  • 8
  • 25
  • 2
    Can you point us to the line in your code that goes wrong? I have a hard time understanding your design and problem. – Patrick Hofman Mar 17 '16 at 12:04
  • when Foo calls SetEventHandler() in the constructor. Even though i have instantiated inst, inst appears as null when i try to assign inst.otherstuff = 123. – CJC Mar 17 '16 at 12:10

2 Answers2

4

You have another variable inst which you have created in Foo (note the new keyword):

public new IBar inst { get; set; }

It hides the other inst you have in your base class. So you are not setting FooBase.inst in Foo, you are setting Foo.inst. Hence, FooBase.inst is null.

You could explictly implement the interface member:

public class Foo : FooBase, IFoo
{
    IBar IFoo.inst { get { return instAsIBar; } set { instAsIBar = value; } }

    public IBar instAsIBar { get { return (IBar)this.inst; } set { this.inst = value; } }
}
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • definately agreed, but my question is how can i set Foo.inst and FooBase.inst together. Because i know Foo,inst is actually a type derived from the type of FooBase,inst so actually i want them both to be linked together. – CJC Mar 17 '16 at 15:44
  • I think it is almost correct, but the set is setting directly as the type of the internal IBarBase. Now i cant access any of the properties defined in IBar. How do i also set the properties of both simultaneously? – CJC Mar 17 '16 at 16:12
  • You mean like `instAsIBar` in my updated code? Setting the one property does also set the other one, since it just encapsulates the other. – Patrick Hofman Mar 17 '16 at 16:14
  • Yes this works i think, but i would have to change all references to be from instAsIBar in order to access the properties of IBar. Is it possible to use the same name ie inst? – CJC Mar 17 '16 at 16:45
  • Not really. Sorry. – Patrick Hofman Mar 17 '16 at 16:45
  • No worries. Thank you so much anyway. You are a champion. Just one more small question. What this means is that, when i will need to access IBar stuff from inst, i will have to cast it explicitly as IBar first before being able to do anything. Is my understanding correct? – CJC Mar 17 '16 at 16:58
1

You should use an explicit implementation of the interface rather than overriding the instproperty:

public class Foo : FooBase, IFoo
{
   public Foo() 
   {
        inst = new Bar();
        SetEventHandlers();
   }

   IBar IFoo.inst { get; set; }
}

Then this test passes:

[TestFixture]
public class TC 
{
    [Test]
    public void t() 
    {
        Foo f = new Foo();
        ((FooBase)f).inst.otherStuff.Should().Be(123);
    }
}
Community
  • 1
  • 1
stuartd
  • 70,509
  • 14
  • 132
  • 163