【问题标题】:Upcast an object向上投射一个对象
【发布时间】:2012-02-07 11:01:30
【问题描述】:

我正在寻找一种方法来获取向上转换对象的可能类型。 例如:我有一个 MyControl 类型的控件,它继承了 Control。现在,当 MyControl 类型的对象向下转换为 Control 时,有办法找出它是否是顶级对象类型,或者现在何时获取可以向上转换的类型(在本例中为 MyControl) ? 我希望它向上转换到 MyControl(带有反射)并获得带有反射的属性。但我不知道 MyControl 在我必须这样做的地方。

MyControl 是用 new 实现的 Visible。现在当我调用 control.Visible = true 时,它​​会调用 Control 的 Visible 但我必须调用 MyControl 的 Visible。

感谢您的帮助。

【问题讨论】:

  • 相信你把upcasting和downcasting的意思颠倒了。向上转换是指从派生类转换为基类向上继承层次结构(例如,MyControlControl)。向下转换是与 向下 继承层次结构相反的方式。在 C# 中向上转换是隐式的,您不必在代码中写出来。

标签: c# .net reflection casting upcasting


【解决方案1】:

你也可以这样用:

MyControl myControl = someControlOfTypeMyControl as MyControl

if(myControl != null)
{
   //your stuff
}

使用“as”.net 框架检查控件是否来自该类型以及是否可以转换,.NET Framework 将转换并返回 MyControl 类型,否则将返回 null。

所以基本上,它与以前的答案相同,但更干净(恕我直言,你可以想不同)

【讨论】:

  • 虽然 OP 可能不会遇到这个问题,但值得注意的是 as 运算符仅适用于引用类型。
  • 我知道这一点 - 但有没有办法在不知道 MyControl 的情况下进行投射 - 仅用于反射?
  • 是的,但是告诉我们您是如何获得对象类型的信息的?作为字符串?
【解决方案2】:

有:

if (myControl is MyControl)
{
    var m = (MyControl)myControl;
}

这适用于类型层次结构的任何部分。如果变量本身是基本类型,则以下检查将不起作用

MyBaseControl myControl = null;

if (myControl.GetType() == typeof(MyControl))
{

}

但是听起来你想要被覆盖的方法或属性的行为。在正常情况下,你会覆盖Visible

public override bool Visible
{
    get { return true; } // Always visible in derived class.
}

但这仅适用于基类未密封且您要覆盖的成员为abstractvirtual 的情况。如果不是这种情况,那么我会坚持转换为派生类型...不理想,但选择不多。

听起来你也试图像这样隐藏基本成员:

public new bool Visible
{
    get { return true; }
}

这仅在您引用类型本身时才有效。如果您有对基类型的引用,则隐藏成员不起作用,它不知道该成员隐藏在派生类型中:

MyBaseControl c = new MyDerivedControl();

bool vis = c.Visible; // Comes from MyBaseControl even if hidden in derived control.

(在上面,如果Visible 被覆盖,那么它将来自派生类)。

更新:要在运行时执行任何此操作,只要您知道要反映的事物的名称,就可以执行以下操作:

class Program
    {
        static void Main(string[] args)
        {
            A a = new B();

            // Get the casted object.
            string fullName = a.GetType().FullName;
            object castedObject = Convert.ChangeType(a, Type.GetType(fullName));

            // Use reflection to get the type.
            var pi = castedObject.GetType().GetProperty("Visible");

            Console.WriteLine(a.Visible);
            Console.WriteLine((bool)pi.GetValue(castedObject, null));

            Console.Read();
        }
    }    

    class A
    {
        public bool Visible { get { return false; } }
    }

    class B : A
    {
        public new bool Visible { get { return true; } }
    }
}

【讨论】:

  • 我知道这一点 - 但有没有办法在不知道 MyControl 的情况下进行投射 - 仅用于反射?
  • @t.kehl 我相信有办法,给我一点时间来测试一下。
  • @t.kehl 用一个版本更新了我的答案,该版本只假设您知道要在每个项目上调用 Visible。它向上转换对最顶层派生类的引用,然后针对您要调用的成员运行反射。
  • 非常感谢。 Convert.ChangeType() 是关键:-)
【解决方案3】:
Control control = (control)someControlOfTypeMyControl;

if (control is MyControl) {
    var myControl = (MyControl)control;
    var propertyValue = myControl.SomeProperty;
}

【讨论】:

  • 我知道这一点 - 但有没有办法在不知道 MyControl 的情况下进行投射 - 仅用于反射?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 2019-06-24
  • 1970-01-01
  • 2019-08-25
  • 2017-08-12
  • 1970-01-01
相关资源
最近更新 更多