C# 将子类强制转换为其超类,但仍然能够使用子类方法和属性

C# 将子类强制转换为其超类,但仍然能够使用子类方法和属性,c#,C#,我试图找到一种方法将一个类强制转换为它的超类,并且仍然使用该类公开的方法和属性。检查下面的代码 public class Car { } public class Audi : Car { private int _Mileage; public int Mileage { get { return _Mileage; } set { _Mileage = value;} } } public class BMW

我试图找到一种方法将一个类强制转换为它的超类,并且仍然使用该类公开的方法和属性。检查下面的代码

public class Car
{        
}

public class Audi : Car
{
    private int _Mileage;
    public int Mileage
    {
        get { return _Mileage; }
        set { _Mileage = value;}
    }
}

public class BMW : Car
{
    private int _Mileage;
    public int Mileage
    {
        get { return _Mileage; }
        set { _Mileage = value;}
    }
}

public class Program
{
    //outside this class either a BMW class or Audi class is instantiated
    Audi _newCar = new Audi();

    // I don't know which one it is so I use a generic type
    Car MyCar;

    int Mileage;

    Program()
    {
        // Now I cast the unknown class to the car type
        MyCar = _newCar;

        // Although I know both Audi & BMW have the Mileage property, I cannot use it
        Mileage = MyCar.Mileage;
    }
}
汽车、奥迪、宝马类是框架的一部分,我无法更改它们。此框架要么返回一辆奥迪或宝马(或其他众多车型之一)

为了获得里程数,我不想为所有可能的品牌创建完全相同的方法。但是,当我将它转换到它的超类时,我再也不能访问Milege属性了


我应该如何解决这个问题?

这是应该如何解决的:

public class Car
{     
    public int Mileage
    {
        get ;
        set ;
    }   
}

public class Audi : Car
{
    public override string ToString()
    {
        return "I'm a Audi";
    }
}

public class BMW : Car
{
    public override string ToString()
    {
        return "I'm a BMW";
    }
}

public class Program
{
    //outside this class either a BMW class or Audi class is instantiated
    Audi _newCar = new Audi();

    // I don't know which one it is so I use a generic type
    Car MyCar;

    int Mileage;

    Program()
    {
        // Now I cast the unknown class to the car type
        MyCar = _newCar;

        // Although I know both Audi & BMW have the Mileage property, I cannot use it
        Mileage = MyCar.Mileage;
    }
}

这是所有汽车的里程数

看起来框架设计得很糟糕。他们应该在所有支持里程跟踪的系统上都设置一个界面,这样你就可以在可用的情况下进行转换,并从界面中提取里程

由于您提到没有对框架类的控制权,所以您只有几个选项。您可以尝试检测其类型并将其投射以提取里程数,也可以使用反射。后者可能是你最好的选择

有关如何获取属性值的示例,请参见

对您来说,最大的区别在于,因为您不确定Miledge属性是否存在,所以需要在调用
type.GetProperty(…)
之后进行检查

编辑以添加样本

使用反射:

static void Main(string[] args)
    {
        Audi _newCar = new Audi() { Mileage = 10 };
        Car myCar = _newCar;

        // Using Reflection
        var propInfo = myCar.GetType().GetProperty("Mileage");
        if (propInfo != null)
        {
            Console.WriteLine(propInfo.GetValue(myCar));
        }

        // Using dynamic
        dynamic myCarDyn = myCar;

        Console.WriteLine(myCarDyn.Mileage);
    }

多级继承是一种选择,试试吧

公车 {

}

公共类MyCustomizedCar:Car { 私人国际里程; 公共国际里程 { 获取{return} 设置{u里程=值;} } }

大众级奥迪:MyCustomizedCar {

}

大众级宝马:MyCustomizedCar {


}

看起来您必须与糟糕的框架作斗争。
克服这一问题的可能方法是使用反射或动态。如果有许多可能的值。如果您知道只有少数几种可能性,并且在此上下文中可以建立对它们的依赖关系,那么您只需检查确切的类型并对其进行强制转换。

我将使用反射来获取属性:

try
{
    Mileage = (int)MyCar.GetType().GetProperty("Mileage").GetValue(MyCar, null);
}
catch (Exception e)
{
    // in this case, the instance has no property named "Mileage"
}
不要忘记导入正确的命名空间:

using System.Reflection;

嘿,托马斯,我知道。这就是为什么我解释说,汽车、奥迪和宝马是一个框架的一部分,我不能改变这一点。当你把
Car
I的代码放进去时,我想你可以改变它:/你为什么要选超类?框架是否返回一辆汽车或一辆奥迪/宝马?请确保我理解正确:您不能更改
汽车
奥迪
宝马
?很好,nodots。我不知道为什么我在最初的回答中盲目地发现了这个选项。嘿,特拉维斯,我知道这个属性对于可以给出的每个类都存在。我不知道如何将你给出的链接转换成这个例子。你能给我一个这个设置的例子吗?我使用了动态方法,它工作得非常出色。我已经重写了代码,可以删除近50%!我确实必须引用Microsoft.CSharp才能使其工作,并更改一些方法,使其参数转换为特定类型才能使Linq工作,但它的工作方式很有魅力。谢谢嘿,Treze,如果我强制转换为确切的类型,这意味着我必须对代码中所有可能的类型进行更改,对吗?