【问题标题】:Can I store a list of types and access their static properties through an interface?我可以存储类型列表并通过接口访问它们的静态属性吗?
【发布时间】:2020-10-01 09:20:57
【问题描述】:

假设我有一个接口 ICar:

public interface ICar
{
    static int WheelSize { get; }
}

我有两个实现接口的类:

class FirstCar: ICar
{
    static int WheelSize { get; } = 28;
}

class SecondCar : ICar
{
    static int WheelSize { get; } = 24;
}

我想将这些类型存储在一个列表中,并检索它们的静态属性,而无需在类型对象上调用 GetProperty("propName")Value(Null):

List<Type> cars = new List<Type>();

cars.Add(typeof(FirstCar));
cars.Add(typeof(SecondCar));

foreach (Type car in cars)
{
    // I want to do something like this:
    int size = ICar<car>.WheelSize;

    // But I currently have to do this:
    size = (int)car.GetProperty("WheelSize").GetValue(null);
    // or this:
    size = (int)car.GetProperty(nameof(ICar.WheelSize)).GetValue(null);
 }

有没有办法存储实现已知接口的类型列表,并以强类型方式访问它们的静态属性?

我会(也许天真地)喜欢直接存储泛型列表而不是创建类型对象,但我认为这根本不可能?

提供有关我想解决的问题的更多信息:

我想显示一个下拉框,其中显示您可以创建的汽车类型(因此在本例中,一个包含 FirstCar 类型和 SecondCar 类型的列表)。我想显示它们各自的 WheelSizes 而无需创建每个实例(属性是静态的,所以我为什么需要创建实例?)。结果,我存储了可以创建的类型列表,而不是对象的实例。不幸的是,我可以从 Type 对象访问 WheelSize 属性的唯一方法是使用字符串根据属性名称检索值,这感觉不对。

跟进: 正如 Guru Stron 所指出的,我可以将接口属性更改为字符串,它仍然可以编译。因此,类属性与接口属性不同,因此,我不能指望能够通过接口解析它们。我不能说我理解为什么它们不一样,但它们不一样的事实一定是我不能做我想做的事情的(或一个)原因。

【问题讨论】:

  • 您的理论的问题在于,它们是两个不同的类。 WheelSize 与类共存,而不是与对象实例共存,它们是两个不同的静态属性,一个都没有。
  • 您能多谈谈您要解决的实际问题吗?您想存储类型列表,还是只想在所有类实例之间共享一个公共属性?
  • 代码在 Core 3.1 项目中为我编译和运行,我使用 GetProperty 获得了正确的大小。
  • @RobertHarvey you can:从 C# 8.0 开始,接口可以为成员定义默认实现。它还可以定义静态成员,以便为通用功能提供单一实现。
  • 要解决的问题是我想显示一个用户可以创建的不同类型汽车的列表,而实际上不必创建每辆汽车的实例来检索它们各自的属性。在这个汽车类比中,每辆汽车的某些方法需要不同的实现,所以我会将汽车类型分成不同的类。

标签: c# .net generics types interface


【解决方案1】:

你可以这样做:

var dict = new[] { typeof(FirstCar), typeof(SecondCar) }
    .Select(t => new 
     {
         Type = t,
         Func = (Func<int>) t.GetProperty("WheelSize", BindingFlags.NonPublic | BindingFlags.Static).GetMethod.CreateDelegate(typeof(Func<int>))            
     })
    .ToDictionary(d => d.Type, d => d.Func);

Console.WriteLine(dict[typeof(FirstCar)]()); //28

【讨论】:

  • 这与我已经用于访问该属性的代码不同吗?它仍然迫使我通过字符串访问属性,而不是对其进行强类型化。
  • 那我不关注你的问题了。
  • 我有两种我知道实现静态属性的类型。我可以使用强类型检索那些静态属性值吗?提议的解决方案只是将弱类型转移到其他地方。
  • @Soy31 将汽车类型上的WheelSize 声明为公开并使用SecondCar.WheelSize
  • @Soy31 看来您对静态接口有误解。您的汽车类型没有实现ICar.WheelSize,它们甚至返回不同的类型。您可以从具体类型中删除WheelSize,代码仍然可以编译。
猜你喜欢
  • 2014-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-21
  • 2013-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多