如果一个类碰巧实现了接口中的所有方法(但没有明确地实现它),有没有办法将类的实例强制转换为该接口?
为了演示这个问题,我设置了以下简单类。 Scavenger
是我要进行单元测试的演示class
。
IFinder
interface
可以由dictionary
实现(或者可以通过其他方式实现)。 Finder是界面的示例实现,使用字典来处理提升。
//System under test
public class Scavenger
{
private readonly IFinder _lookup;
public Scavenger(IFinder lookup)
{
_lookup = lookup;
}
public string WhatIs(string key)
{
if (_lookup.ContainsKey(key)) return _lookup[key];
return null;
}
}
//Interface that can be met by a dictionary
public interface IFinder
{
bool ContainsKey(string key);
string this[string key] { get; set; }
}
//Implement IFinder using a dictionary
public class Finder : Dictionary<string,string>, IFinder
{
public Finder()
{
this.Add("A","Hello");
this.Add("B","Goodbye");
}
}
我希望能够沿着这些路线为Scavenger设置测试...
/// <summary>
/// This will fail because due to failed cast a Dictionary to an IFinder
/// </summary>
[TestMethod]
public void LookupUsingDictionary()
{
var dic = new Dictionary<string, string>();
dic.Add("A","B");
var scavenger = new Scavenger(dic as IFinder);
var res = scavenger.WhatIs("A");
Assert.AreEqual("B", res);
}
问题在于(dic as IFinder) == null
。我知道我可以设置一个类似于Finder的模拟类,或者使用模拟框架,但我只是想要检查我是否缺少某种方法来编写字典来完成这项工作。
答案 0 :(得分:3)
当您有一个接口和一个实现所有适当方法的类但没有实现该接口时,您可以使用适配器模式来实现您的目标。创建一个实现给定接口的类,并接受具有所有所需方法的类型的实例。然后,它可以将所有方法重定向到组合类:
public class DictionaryFinder : IFinder
{
private Dictionary<string, string> dictionary;
public DictionaryFinder(Dictionary<string, string> dictionary)
{
this.dictionary = dictionary;
}
public bool ContainsKey(string key)
{
return dictionary.ContainsKey(key);
}
public string this[string key]
{
get { return dictionary[key]; }
set { dictionary[key] = value; }
}
}
这允许你写:
var scavenger = new Scavenger(new DictionaryFinder(dic));
答案 1 :(得分:2)
不,你不能这样做。这称为duck typing和C#不允许这样做。
答案 2 :(得分:1)
您可以使用dynamic
关键字来完成此操作......
像这样制作你的清道夫类:
public class Scavenger
{
private readonly dynamic _lookup;
public Scavenger(dynamic lookup)
{
_lookup = lookup;
}
public string WhatIs(string key)
{
if (_lookup.ContainsKey(key)) return _lookup[key];
return null;
}
}
这将尝试在运行时找到方法。有关详情,请参阅:http://msdn.microsoft.com/en-us/library/dd264741.aspx
答案 3 :(得分:1)
您可以使用ImpromptuInterface。我用它来实际上做类似鸭子的行为。
在某种程度上,由于4.0中引入的动态语言运行时(我相信它是4.0),C#确实允许鸭子打字,只是要非常小心你不要自己烧。 ImpromptuInterface证明了这一点。