【问题标题】:OfType to access Generic Parent classOfType 访问通用父类
【发布时间】:2015-10-08 08:54:15
【问题描述】:

我有以下类/接口:

  • public interface IUiCommand
  • public class StartLandenSynchronisatieUiCommand : IUiCommand; public class SyncGeldverstrekkersUiCommand : IUiCommand;等
  • public class RibbonButtonAggregateViewModel<TCommand> : RibbonButtonViewModel<TCommand> where TCommand : IUiCommand
  • public abstract class RibbonButtonViewModel<TCommand> : ResizableRibbonItem where TCommand : IUiCommand
  • RibbonButtonViewModel 的其他一些实现类。

RibbonButtonViewModel 包含一个属性KeyTip

在我正在处理的 UnitTest 中,我有一个包含两个项目的列表:RibbonButtonAggregateViewModel<StartLandenSynchronisatieUiCommand>RibbonButtonAggregateViewModel<SynGeldverstrekkersUiCommand(这只是一个示例,我有更多列表具有不同的 IUiCommands 或其他实现的 @ 类987654333@).

我想要的是这个列表作为 RibbonButtonViewModels,这样我就可以在 for-each 中访问他们的 KeyTip-property。

基于这个SO question & answer,我能够正确过滤列表,所以我仍然有两个列表:

// `items` is the list containing the two RibbonButtonAggregateViewModels
var correctItems = items.Where(x =>
    {
        if (!x.GetType().IsGenericType) return false;
        var baseType = x.GetType().BaseType;
        if (baseType == null || !baseType.IsGenericType) return false;
        return baseType.GetGenericTypeDefinition() == typeof (RibbonButtonViewModel<>);
    })
    .ToList();

即使我正确过滤列表并在 RibbonButtonViewModelsIUiCommand 作为泛型类型时获取这两个项目,但我没有得到 RibbonButtonViewModels 的结果来访问 KeyTip。我尝试在WhereToList 之间添加以下两个之一,但都不起作用:

  • .OfType&lt;RibbonButtonViewModel&lt;IUiCommand&gt;&gt;() -> 结果为空列表
  • .Select(x =&gt; x as RibbonButtonViewModel&lt;IUiCommand&gt;) -> 结果列表中包含两个 null

那么,当我有子项列表时,我应该如何获得RibbonButtonViewModel 的列表来访问KeyTip-属性。 (PS:不必特别是RibbonButtonAggregateViewModel,任何以RibbonButtonViewModel为基础的实现类都可以,只要列表返回为RibbonButtonViewModels,这样我就可以访问KeyTip-property。

【问题讨论】:

    标签: c# linq generics reflection types


    【解决方案1】:

    一种可能的解决方案是创建一个协变的新接口:

    public interface IViewModel<out T> where T : IUiCommand
    {
        string KeyTip { get; set; }
    }
    

    这个接口可以由RibbonButtonViewModel实现:

    public abstract class RibbonButtonViewModel<TCommand> : IViewModel<TCommand> where TCommand : IUiCommand
    {
        public string KeyTip { get; set; }
    }
    

    之后你可以使用这个:

    var correctItems= items.OfType<IViewModel<IUiCommand>>().ToList()
    correctItems[0].KeyTip // is valid
    

    或者您可以使用动态 - 但您将用运行时错误替换编译器错误:

    // `items` is the list containing the two RibbonButtonAggregateViewModels
    var correctItems = items.Where(x =>
    {
        if (!x.GetType().IsGenericType) return false;
        var baseType = x.GetType().BaseType;
        if (baseType == null || !baseType.IsGenericType) return false;
        return baseType.GetGenericTypeDefinition() == typeof (RibbonButtonViewModel<>);
    })
    .ToList<dynamic>();
    correctItems[0].KeyTip = ""; // will compile but fail at runtime if the type doesn't has such a property.
    

    诀窍是.ToList&lt;dynamic&gt;()

    【讨论】:

    • 围绕它创建一个新界面目前并不是一个真正的选择。这个 UnitTest 应该测试的功能几乎没有被用户使用,所以它的优先级很低。 .ToList&lt;dynamic&gt;() 的选项看起来很有希望,所以我会尽快尝试。为此 +1,我会告诉你结果如何。
    猜你喜欢
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 2011-09-21
    相关资源
    最近更新 更多