Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In this MSDN Magazine article Peter Vogel describes Extension Objects partten.

What is not clear is whether extensions can be later implemented by client code residing in a separate assembly.
And if so how in this case can extension get acces to private members of the objet being extended?

I quite often need to set different access levels for different classes.
Sometimes I really need that descendants does not have access to the mebmer but separate class does. (good old friend classes)

Now I solve this in C# by exposing callback properties in interface of the external class and setting them with private methods. This also alows to adjust access: read only or read|write depending on the desired interface.

class Parent
{
    private int foo;

    public void AcceptExternal(IFoo external)
    {
        external.GetFooCallback = () => this.foo;
    }
}

interface IFoo
{
    Func<int> GetFooCallback {get;set;}
}

Other way is to explicitly implement particular interface.

But I suspect more aspproaches exist.

Update 1
New Peter's article makes it a bit clearer.

share|improve this question
    
This sounds like you should rethink your design. –  svick Apr 27 '13 at 9:07
    
Sounds what? The question is how Roles pattern should be implemented when extension needs access to private part of the class. Do you mean that extansible part must be publicly visible? –  voroninp Apr 28 '13 at 8:45
    
A proxy pattern. pg 207 from the GoF book if you want more detail. –  JustinC Jun 27 '13 at 5:25
add comment

1 Answer

I think that you missed a little bit of the point of the article. When he was talking about think in the Extension, he was talking about an concept, and not a particular Design Pattern. There are several Design Patterns that would allow for extension of your objects, this really depends on how you want to do it. Let me quote what 2 think could be the best to allow for extension:

Decorator Pattern:

private interface IPrice
{
    int Price { get; }
}

private class PriceDecorator : Pizza
{
    IPrice _price;

    protected virtual int OriginalPrice { get { return 0; } }

    public virtual int Price
    {
        get { return OriginalPrice + _price.Price; }
    }
    protected PriceDecorator() { }

    public PriceDecorator(IPrice price)
        : this()
    {
        _price = price;
    }
}

private class Pizza : PriceDecorator
{
    public Pizza(IPrice price) : base(price){}
    protected Pizza()  { }

    protected override int OriginalPrice
    {
        get { return 10; }
    }
}

class Cheese : PriceDecorator
{
    protected Cheese()  {    }
    public Cheese(IPrice price) : base(price) { }

    protected override int OriginalPrice
    {
        get { return 2; }
    }
}

class Pepperoni : PriceDecorator
{
    protected Pepperoni() {}
    public Pepperoni(IPrice price) : base(price){ }

    protected override int OriginalPrice
    {
        get { return 1; }
    }
}

class test
{
    void run()
    {
        var pizzaWithCheese = new Pizza(new Cheese());
        var pizzaWithCheeseAndPepperoni = new Pizza(new Cheese(new Pepperoni()));
    }
}

Strategy Design Pattern:

You can read more here

abstract class StrategyBase
{
    public abstract void DoSomething();
}

class ConcreteStrategyA : StrategyBase
{
    public override void DoSomething()
    {
        Console.WriteLine("Called ConcreteStrategyA.DoSomething()");
    }
}

class ConcreteStrategyB : StrategyBase
{
    public override void DoSomething()
    {
        Console.WriteLine("I did something!");
    }
}

/// This is the class that you allow extension, using any of the strategies 
class Context
{
    private StrategyBase _strategy;

    public Context(StrategyBase strategy)
    {
        this._strategy = strategy;
    }

    public void DoSomething()
    {
        _strategy.DoSomething();
    }
}

// Use it like this:
var c = new Context(new ConcreteStrategyA());
c.DoSomething();
share|improve this answer
    
The article contains link to this pattern: mif.vu.lt/~plukas/resources/Extension%20Objects/… The idea is clear, but the implementation is vague. At least for me. Quite often role need access to private members. –  voroninp Jun 26 '13 at 21:58
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.