访问泛型父类

本文关键字:父类 泛型 访问 | 更新日期: 2023-09-27 18:16:32

我有以下类/接口:

  • 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(这只是一个例子,我有更多的列表与不同的IUiCommandsRibbonButtonViewModel的其他实现类)。

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

基于这个SO问题&答案是,我能够正确地过滤列表,所以我仍然有两个列表:

// `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<RibbonButtonViewModel<IUiCommand>>() ->结果为空列表
  • .Select(x => x as RibbonButtonViewModel<IUiCommand>) ->结果列表包含两个null

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

访问泛型父类

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

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

或者你可以使用dynamic -但是你将用运行时错误替换编译错误:

// `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<dynamic>()