要进行单元测试,我有一个假的ScriptManager类型,类似于此定义:
public class FakeScriptManager : ScriptManager
{
public new virtual bool IsNavigating { get; private set; }
}
我的测试方法如下:
public string GetHistoryPoint<TScriptManager>(string key, TScriptManager scriptManager)
where TScriptManager : ScriptManager
{
TScriptManager realScriptManager = Convert.ChangeType(scriptManager, scriptManager.GetType());
if (realScriptManager.IsNavigating)
{
// Do something
}
}
测试方法如下:
using (FakeScriptManager scriptManager = new FakeScriptManager(true, false))
{
object value = _handler.GetHistoryPoint(keyExists, scriptManager);
}
我打算为FakeScriptManager变量设置 NEW 属性 IsNavigating true 。但它无法做到。变量realScriptManager似乎无法从预期的通用TScriptManager类型中生成。
注意: 的 调试,尝试使用具体类型FakeScriptManager直接输入输入参数scriptManager,没关系。
所以,我的问题是:如何使通用类型的GetHistoryPoint方法正常工作? 请问有谁伸出援助之手吗?
答案 0 :(得分:1)
几乎在所有情况下,方法隐藏(new
)都是错误的做法;在几乎所有情况中,更好的方法是override
。我的主要答案是:删除new
。
编译器正在做正确的事情;它只通过IsNavigating
了解TScriptManager : ScriptManager
,所以它使用那个就不足为奇了。 C#泛型不像C ++模板;他们可以使用类型的已知(where
)结构中的多态性等,而不只在名称的基础上寻找实际T
的最佳拟合(鸭子) -typing)。
如果你真的需要这个,那么要么是反射,要么是4.0,dynamic
(完全是鸭子型的):
dynamic obj = scriptManager;
if((bool)obj.IsNavigating) {
...
}
(注意上面的“显式接口实现”可能会失败,但这不是你正在做的事情)
此处的Convert.ChangeType
没有任何用处。