Хотели бы иметь общий класс Wrapper - PullRequest
3 голосов
/ 12 января 2011

Для целей наследования я хотел бы иметь следующий класс, который я не могу написать сам, доступный:

class Wrapper<G> : G
{
    public Wrapper(G base);
    protected G GetBase();
}

Он бы наследовал все члены G как обычные, и все использования этих членов были быперенаправлен на G, предоставленный во время построения.

Было бы технически возможно добавить эту функциональность к языку как C #?

Основной сценарий использования, для которого я хотел бы использовать это:*

    class Wrapper<G> : G
    {
        public Wrapper(G g);
    }

    class IGraphNode<G> where G : IGraphNode<G>
    {
        IEnumerable<G> ForwardNodes();
        IEnumerable<G> BackwardNodes();
    }

    //Reverses the direction of the graph.
    class Reverse<G> : Wrapper<G> where G : IGraphNode<G>
    {
        public Reverse(G g)
            : base(g)
        { }

        IEnumerable<G> ForwardNodes()
        {
            return base.BackwardNodes();
        }

        IEnumerable<G> BackwardNodes()
        {
            return base.ForwardNodes();
        }
    }

Ответы [ 4 ]

1 голос
/ 12 января 2011

Не уверен, что это именно то, что вам нужно, но вы можете использовать DynamicProxy для создания объектов-оболочек во время выполнения и при необходимости перехватывать вызовы методов и свойств.

0 голосов
/ 12 января 2011

Возможно, вы могли бы сделать это с отражением. Но какова ваша цель? Чтобы украсить класс, или создать инструменты, которые делают вещи с ним? Расширение существующего экземпляра класса так, как вы хотите, кажется рискованным, потому что вы не будете создавать новый экземпляр базового класса, а код, который использует объект, не будет знать об этом. То есть свойства могут изменить либо просто новый объект, либо какой-либо другой объект, который он расширяет, и точная функциональность будет неизвестна из синтаксиса.

Я бы подумал, что гораздо прозрачнее (в общем) просто сделать, например

class Wrapper<G> where G: SomeType
{
    public G Base;
    public Wrapper(G g) {
        Base = g;
    }

    // methods to do stuff with object supplied at construction
}

Вы могли бы сделать это без where, но я не могу придумать многих причин, по которым вам было бы все равно, какой это базовый тип.

Если вы действительно хотите создать новый класс, который имеет новые свойства и наследует данные от существующего класса, я думаю, что вы, возможно, слишком стараетесь, потому что это не имеет смысла: два объекта не будут дольше связаны разумным способом. То есть изменения в свойствах базового класса могут повлиять на объект, отличный от изменений в свойствах вашего расширения. Это именно то, что произошло бы, если бы в этом примере у вас были свойства в MyWrapper.Base, но более концептуально более разумно поддерживать ссылку на объект отдельно от базы, если это на самом деле ваша цель. В противном случае клиенты, использующие ваш объект расширения, не поняли бы этого, и вы легко могли бы в конечном итоге не знать, почему ваш код работал неправильно ...

Если вы хотите создать новый объект, который расширяет что-то и копирует свойства существующего объекта некоторым прозрачным способом, то сделайте что-то вроде этого:

class Wrapper<G>: G
{
    public Wrapper(G g) {
        // add memberwise copy function
    }
    .. more properties
}

Wrapper<SomeType> newWrapper = Wrapper<SomeType>(someOtherObject);

.. как то, как вы можете создать новый список из существующего.

0 голосов
/ 12 января 2011

Разве не для этого используются расширения?

public static class MyStringExtensions
{
    public static string Add1ToString(this string myString)
    {
        myString += "1";
        return myString;
    }
}

В другом классе вы можете использовать следующее:

using YourNamespaceOfTheExtensionMethods;

public class OtherClass
{
    public string DoSomething()
    {
        string someString = "Hello";
        return someString.Add1ToString();
    }
}

Я использовал string в качестве примера, но вы можете расширить Object, если хотите.

0 голосов
/ 12 января 2011

Я думаю, что это существует в Ruby, забудь, как это называется.Это не поддерживается в C #.Можно ли добавить эту функциональность в C #?Конечно, если вы сможете убедить команды .Net и C # реализовать это ... но я сомневаюсь, что они это сделают.

...