我有以下类/接口:
-
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
或RibbonButtonViewModel
的其他实现类)。
我想要的是这个列表作为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();
即使我正确过滤列表并在RibbonButtonViewModels
与IUiCommand
作为泛型类型时获得这两个项目,我也没有得到RibbonButtonViewModels
的结果来访问KeyTip
。我尝试在Where
和ToList
之间添加以下两个中的任何一个,但两者都不起作用:
-
.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>()