C# 使用反射获取静态属性值,派生类和基类的串联

C# 使用反射获取静态属性值,派生类和基类的串联,c#,reflection,C#,Reflection,我将尽我所能在这里解释我的愿景。这是一个非常蹩脚的虚构的例子。我有几种不同类型的包s,它们都有自己特殊类型的大理石。每种类型的Marble都有自己的昵称集(strings) 不幸的是,包里除了大理石还有其他东西,所以仿制药在这里帮不了我 // Bags abstract class Bag { protected Type MarbleType { get; } protected List<Marble> _marbles; public void Dum

我将尽我所能在这里解释我的愿景。这是一个非常蹩脚的虚构的例子。我有几种不同类型的
s,它们都有自己特殊类型的
大理石
。每种类型的
Marble
都有自己的昵称集(
string
s)

不幸的是,包里除了大理石还有其他东西,所以仿制药在这里帮不了我

// Bags
abstract class Bag {
    protected Type MarbleType { get; }
    protected List<Marble> _marbles;

    public void DumpBag()
    { ... }
}
class RedBag : Bag {
    override Type MarbleType { get { return typeof(RedMarble); } }
}
class BlueBag : Bag {
    override Type MarbleType { get { return typeof(BlueMarble); } }
}

// Marbles
abstract class Marble {
    public static IEnumerable<string> Nicknames {
        get {
            return new List<string>() {
               "Marble", "RollyThing"
            }
        }
    }
}
class RedMarble : Marble {
    public static IEnumerable<string> Nicknames {
        get {
            return new List<string>(Marble.Nicknames) {
                "Ruby"
            };
        }
    }
}
class BlueMarble : Marble { ... }
我想把它打印出来:

Bag of Marbles (aka "Marble", "RollyThing", Ruby"):
- Marble 1
- Marble 2
...
我们看到,为了打印该标题,
必须能够了解
大理石
的派生类型,而不依赖于任何实际实例。它获取
大理石
基类的
昵称
的串联,以及派生的
红色大理石

DumpBag
需要执行一种“静态虚拟调用”。我已开始实施
DumpBag
,包括以下内容:

public void DumpBag() {
    PropertyInfo pi = this.MarbleType.GetProperty("Nicknames", BindingFlags.Static);
    IEnumerable<string> nicknames = pi.GetValue(null, null);  // No instance

    StringBuilder sb = new StringBuilder("Bag of Marbles (aka ");
    foreach (string nn in nicknames)
        sb.Append("\"" + nn + "\", ");
    Console.WriteLine(sb.ToString());

    ...
}
public void DumpBag(){
PropertyInfo pi=this.MarbleType.GetProperty(“昵称”,BindingFlags.Static);
IEnumerable昵称=pi.GetValue(null,null);//无实例
StringBuilder sb=新StringBuilder(“弹珠袋(aka”);
foreach(昵称中的字符串nn)
sb.附加(“\”+nn+“\”,”);
Console.WriteLine(sb.ToString());
...
}
我的问题是:

  • 这是明智的吗?希望我已经(或者我可以)解释我为什么走这条路的理由
  • 我(当然)收到一条警告,
    红色大理石。昵称
    隐藏
    大理石。昵称
    。继续并将其标记为新的是否有效

  • 你会发现你所缺少的只是一个明确的演员阵容:

    (列表)this.MarbleType.GetProperty(“昵称”).GetValue(null,null);

    当我测试它时,它对我很有效

    正如在评论中所讨论的,不,你不应该使用new关键字。实际上,你最好将基类静态方法命名为其他方法,这样就不会有歧义。毕竟,你可以控制这一点,而不是使用其他人的代码


    现在,你应该这样做吗

    首先,您肯定希望使用泛型而不是定义的方法来返回类型:

    abstract class Bag<T> where T:marble {
        public void DumpBag()
        { 
            // here you can use
            // (IEnumerable<string>)typeof(T).GetProperty("Nicknames").GetValue(null, null);
        }
    }
    
    class RedBag : Bag<RedMarble> {
    }
    
    class BlueBag : Bag<BlueMarble> {
    }
    
    抽象类包,其中T:marble{
    公共垃圾袋()
    { 
    //在这里你可以使用
    //(IEnumerable)typeof(T).GetProperty(“昵称”).GetValue(null,null);
    }
    }
    班级:红包{
    }
    类别:包{
    }
    

    当然,您可以做的第二件事是使它不是静态的,在这种情况下,属性将在
    Marble
    中抽象,并在
    RedMarble
    BlueMarble
    中重写,然后在
    DumpBag
    中直接作为
    昵称访问,而不是使用反射de>Marble.昵称
    ->
    Marble.base昵称
    ,您的代码示例与我的代码示例有什么不同吗?连接就像您在
    RedMarble.昵称
    中所拥有的一样。我使用反射是因为
    本身不知道它处理的
    大理石
    的类型,因此它使用使用虚拟属性来获取
    类型
    ,然后使用反射来获取该类型的静态属性。一定错过了代码的一部分-请注意,您有
    大理石。名称
    不是
    大理石。昵称
    ,这让我很反感。要回答您问题的第2部分,请不要将其标记为新的,这不是真正的继承。啊,我的道歉-不是帽子应该是昵称,修正了。
    abstract class Bag<T> where T:marble {
        public void DumpBag()
        { 
            // here you can use
            // (IEnumerable<string>)typeof(T).GetProperty("Nicknames").GetValue(null, null);
        }
    }
    
    class RedBag : Bag<RedMarble> {
    }
    
    class BlueBag : Bag<BlueMarble> {
    }