繁体   English   中英

如何访问从通用类继承的对象?

[英]How can an object be accessed that inherits from a generic class?

这让我很头疼,我希望有人愿意找到解决办法。 右下方是情况的简化代码。 这里的目的是,我想要一个单独的,可重用的库,并可以选择为每个实现自定义这些类。 所以我去继承:

namespace Library {

   //a class that holds stuff together
   public class Core<THandler> where THandler:Handler
   {
      public THandler handler;
      public string text = "Something";
   }

   //class that react for extern events, say a keyboard events
   public class Handler 
   {
      protected object core;
      public Handler(object _core) {
         core = _core;
      }
      protected virtual void OnEvent() {
         //how to access 'core.text' ??
         var a = (Core<Handler>)core; //raises System.InvalidCastException 
                                      // since 'core' actualy contains 
                                      // an instance of MyCore
      }
   }
}
namespace MyImplementation {
   public class MyCore : Library.Core<MyHandler>
   {
   }

   public class MyHandler : Library.Handler
   {
      protected override void OnEvent() {
         base.OnEvent();
         //and what's the preferable option for accessing 'core' here?
         var a = (MyCore)core; //I use this
      }
   }
}

由于Handler.core包含MyCore的一个实例,因此如何在Hanlder.OnEventmethod中访问此对象?

最好的方法(无论如何,在我看来)是为需要在Core访问的方法和属性创建一个接口。

例如,类似于以下内容:

namespace Library {

    public interface ICore {
        string text {get; set;}
    }

   //a class that holds stuff together
    public class Core<THandler> : ICore where THandler : Handler
    {
        public THandler handler;
        private string m_Text = "Something";
        public string text
        {
            get
            {
                return m_Text;
            }
            set
            {
                m_Text = value;
            }
        }
    }

   //class that react for extern events, say a keyboard events
   public class Handler 
   {
      protected ICore core;
      public Handler(object _core) {
         core = (ICore)_core;
      }
      protected virtual void OnEvent() {
          Debug.WriteLine(core.text);
      }
   }
}

namespace MyImplementation {
   public class MyCore : Library.Core<MyHandler>
   {
   }

   public class MyHandler : Library.Handler
   {
      protected override void OnEvent() {
         base.OnEvent();
         //and what's the preferable option for accessing 'core' here?
         var a = (MyCore)core; //I use this
      }
   }
}

使用接口将CoreHandler相互绑定会更好。 您仍然可以保持Core<T>通用。 泛型类型约束不允许您声明循环依赖关系,否则就必须进行核心工作。

请注意,有问题的MyCore无效的根本原因不是您的示例中的core实例是MyCore ,而是因为MyCore继承自Core<MyHandler>而不是Core<Handler>

如果由于某种原因,您坚持要保持当前的设计,则也可以使Handler通用,将其祖先作为类型参数传入,并像下面这样修复类型转换:

public class Handler<THandler> where THandler : Handler<THandler>
{
    protected object core;
    public Handler(object _core) {
        core = _core;
    }
    public virtual void OnEvent() {
        // this works
        var a = (Core<THandler>)core;
    }
 }

因此,为了使其更具类型安全性并避免强制转换,构造函数应如下所示:

    protected Core<THandler> core;
    public Handler(Core<THandler> _core) {
        core = _core;
    }

然后,很自然地, MyHandler声明将如下所示:

public class MyHandler : Handler<MyHandler>
{
    …
}

强制转换失败,因为Core不协变。 一般而言,类不能协变。 只有接口和委托可以是协变的。

为了达到预期的行为,您可以将Core类定义为带有out参数的接口,如下所示

public interface ICore<out T>where T:Handler
{
    T Handler {get;}
    string Text { get; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM