【问题标题】:How the get derived class type from base class如何从基类获取派生类类型
【发布时间】:2019-09-05 06:50:42
【问题描述】:

我正在尝试重构我在很多类中使用的方法。举例说明比较简单。

我有这门课:

    public class TipoPuntoClaveConst
    {
        public const int Insercion = 1;
        public const int DetectorDePaso = 2;
        public const int Sincronizador = 3;
        public const int Extraccion = 4;

        public static string GetDescripcion(int IdxTipo)
        {
            var property = typeof(TipoPuntoClaveConst)
                .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
                .Where(fi => fi.IsLiteral && !fi.IsInitOnly && (int)fi.GetRawConstantValue() == IdxTipo)
                .FirstOrDefault();

            if (property == null) return string.Empty;
            var name = property.Name;
            return ResourceHelper.GetTraduccion(ResourceHelper.FICHERO.General, name);
        }
    }

在项目中,我还有一个用于本地化的 ResourceFile。 GetDescription 方法使用给定值的正确属性名称返回本地化文本。可以看一个使用示例:

<html>
    <body>
        <select id="cbTipo">
            <option value="@TipoPuntoClaveConst.Insercion">@TipoPuntoClaveConst.GetDescripcion(TipoPuntoClaveConst.Insercion)</option>
            ...
        </select>
    </body>
</html>

问题是,我必须在我的所有 const 类中复制粘贴该方法。我正在尝试在基类中实现此方法,例如:

public class TipoPuntoClaveConst : ConstMaster {...}

public class ConstMaster {
    public static string GetDescripcion(int IdxTipo)
    {
        var property = typeof(TipoPuntoClaveConst)
            .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
            .Where(fi => fi.IsLiteral && !fi.IsInitOnly && (int)fi.GetRawConstantValue() == IdxTipo)
            .FirstOrDefault();

        if (property == null) return string.Empty;
        var name = property.Name;
        return ResourceHelper.GetTraduccion(ResourceHelper.FICHERO.General, name);
    }
}

但我不知道如何将var property = typeof(TipoPuntoClaveConst) 替换为更通用的东西,例如var property = typeof(¿this?)

【问题讨论】:

  • 你为什么不Type myType = this.GetType()
  • 因为GetDescripcion是静态方法
  • 如果你没有声明方法静态并且在基类中你this.GetType()在一个方法中,当实例化一个子/继承类并在子实例中调用该方法时,你会得到正确的类型(孩子/继承的)。
  • @bradbury9 我知道,但我不想删除 static 如果你看一下我们的例子,我并没有声明一个对象来调用该方法,所以,通过删除它我将不得不检查我的所有代码以纠正我所有的 const 类。
  • 您希望它是静态的,但不想实例化,好的,刚刚编辑了我的答案。

标签: c# hierarchy


【解决方案1】:

只要您的问题与类型和继承有关,我就会向您解释您拥有的替代方案,但要避免反射部分。

  1. 使用this.GetType()获取类型的非静态方法
  2. 静态方法,提供类的实例作为函数 参数。
  3. 静态泛型方法,不提供实例。

因为简单,我会选择非静态的,但这取决于你想给它的用法。根据您的问题,您可以利用泛型。

namespace InheritanceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine($"Base: {new BaseClass().CheckType()}");
            Console.WriteLine($"Child: {new ChildClass().CheckType()}");
            Console.WriteLine($"Static in base with child argument: {BaseClass.CheckType(new ChildClass())}");
            Console.WriteLine($"Static generic in base:{BaseClass.CheckType<ChildClass>()}");
            Console.ReadLine();
        }
    }

    public class BaseClass
    {
        public string CheckType()
        {
            return this.GetType().ToString();
        }

        public static string CheckType(BaseClass instance)
        {
            return instance.GetType().ToString();
        }

        public static string CheckType<T>() where T: BaseClass
        {
            return typeof(T).ToString();
        }
    }

    public class ChildClass : BaseClass
    {
    }
}

输出如下

Base: InheritanceTest.BaseClass
Child: InheritanceTest.ChildClass
Static in base with child argument: InheritanceTest.ChildClass
Static generic in base: InheritanceTest.ChildClass

【讨论】:

  • 感谢您的放大,但我想我将无法按照我的想法去做。主要问题是避免审查该方法的所有用途。 TipoPuntoClaveConst 只是其中一个类,但我有一堆`xxxConst` 类。他们都用他自己的static GetDescripcion 方法。您给我的所有解决方案都是很好的解决方案,但是需要付出中等的努力来改变所有用途,要么在使用方法之前声明一个对象,要么将一个对象作为参数传递。也许是下一个冲刺:)
【解决方案2】:

当您调用GetDescription 方法时,它将是基类对象本身或某个派生类对象。但是在基础上,您不知道它是哪个派生类。您将需要使用 GetType 方法在运行时获取它的实际类型,如 cmets 中提到的 @bradbury9 所述:

public string GetDescripcion(int IdxTipot)
{
    var property = this.GetType()
            .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
            .Where(fi => fi.IsLiteral && !fi.IsInitOnly && (int)fi.GetRawConstantValue() == IdxTipo)
            .FirstOrDefault();

   if (property == null) return string.Empty;
    var name = property.Name;
    return ResourceHelper.GetTraduccion(ResourceHelper.FICHERO.General, name);
}

最好将其保留为实例方法,如果您确实需要将其作为静态方法,则需要将对象作为参数输入:

public static string GetDescripcion(int IdxTipo,TipoPuntoClaveConst objec)
{
    var property = object.GetType()
            .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
            .Where(fi => fi.IsLiteral && !fi.IsInitOnly && (int)fi.GetRawConstantValue() == IdxTipo)
            .FirstOrDefault();

   if (property == null) return string.Empty;
    var name = property.Name;
    return ResourceHelper.GetTraduccion(ResourceHelper.FICHERO.General, name);
}

【讨论】:

  • But in base you don't know which dervied class it is 如果没有办法知道,那我根本做不到我想做的事。将方法保留在派生类中是我想要避免的,因为我必须在所有类中复制相同的代码。但是,如果将该代码移动到基类,意味着更改参数,我不能假设修改。然后,我将不得不更改所有代码以更新对该方法的所有调用。感谢您的帮助
  • 建议并编辑您的答案,您的第二个代码 sn-p 需要 TipoPuntoClaveConst object 参数,而您的第一个代码需要 this.GetType()
  • @bradbury9 谢谢,我首先编辑了它,但更改丢失了一些方式
  • 可能是模组,虽然我改动太多,所以我添加了评论
猜你喜欢
  • 2015-03-30
  • 1970-01-01
  • 2010-11-01
  • 2012-07-09
  • 1970-01-01
  • 2011-03-05
  • 2013-10-15
  • 2016-02-23
  • 1970-01-01
相关资源
最近更新 更多