【问题标题】:Would like to have a generic Wrapper class available希望有一个通用的 Wrapper 类可用
【发布时间】:2011-06-07 21:14:35
【问题描述】:

出于继承目的,我希望提供以下我自己无法编写的类:

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();
        }
    }

【问题讨论】:

  • 你有更具体的例子来说明 G 是什么以及 Wrapper 需要做什么?
  • 常规继承有什么问题?已经实现的那种?
  • '扩展' ? c#,你的意思是java吗?
  • 我相信他想扩展G 类型对象的功能。但这不正是 .Net 中使用的扩展名。请参阅下面的示例。
  • 您是否尝试使用装饰器模式?见:dofactory.com/Patterns/PatternDecorator.aspx#_self1

标签: c# .net class inheritance wrapper


【解决方案1】:

不确定这是否是您想要的,但您可以使用DynamicProxy 在运行时创建包装对象并根据需要拦截方法和属性调用。

【讨论】:

    【解决方案2】:

    我认为这存在于 Ruby 中,忘记它叫什么了。这在 C# 中不受支持。是否可以在 C# 中添加此功能?当然,如果你能说服 .Net 和 C# 团队实现这一点......但我怀疑他们会这样做。

    【讨论】:

    • 在 C++ 中它被称为 CRTP(奇怪的重复模板模式)。在 Ruby 中,它可能也被称为“mixin”,尽管这在技术上是另外一回事,但 CRTP 有时用于在 C++ 中实现 mixin。
    • @Konrad:很有趣。我认为它是 Ruby 中的委托模式。
    【解决方案3】:

    这不就是扩展的用途吗?

    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

    【讨论】:

    • 我相信他希望所有对 GenericExtensions 上的 MyClassA 方法的调用都调用 MyClassA 实例的方法。如果这是有道理的...... :)
    • 我注意到在我发布答案之后:)
    • 删除了第一个答案,因为我认为他可能正在使用扩展。
    【解决方案4】:

    您可能可以通过反射来做到这一点。但你的目标到底是什么?装饰一个班级,或创建与之相关的工具?以您想要的方式扩展类的现有实例 似乎有风险,因为您不会创建基类的新实例,并且使用该对象的代码不会意识到这一点。也就是说,属性可以只更改新对象,也可以更改它扩展的其他对象,并且从语法中无法得知确切的功能。

    我认为(通常)这样做会更加透明,例如

    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);
    

    .. 就像您如何从现有列表创建新列表一样。

    【讨论】:

    • 我认为他想要的是扩展方法。我的猜测是他想为已经存在的类“添加”一些功能,这就是扩展方法的用途。
    • 认为你可能是对的。不过,我仍然觉得有一些不可告人的动机,因为如果使用您自己的对象,为什么不将这些方法包含在核心设计中,或者使用基类和继承来创建对象的不同用途版本?但是,是的,如果他的目标只是装饰别人的东西,那就是这样。不知何故,虽然我的直觉说他想添加属性,而不仅仅是方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多