[英]Cast a class that implements all of the methods in an interface
If a class happens to implement all of the methods in an interface (but doesn't explicitly implement it), is there a way of casting an instance of the class to that interface? 如果一个类恰好实现了接口中的所有方法(但未明确实现),是否可以将类的实例强制转换为该接口?
To demonstrate the issue I've set up the following simple classes. 为了演示这个问题,我设置了以下简单的类。 Scavenger
is a demonstration class
that I want to unit test. Scavenger
是我要进行单元测试的演示class
。
The IFinder
interface
can be implemented by a dictionary
(or could be implemented some other way). IFinder
interface
可以由dictionary
实现(或可以通过其他方式实现)。 Finder is a sample implementation of the interface using a dictionary to handle the lifting. 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");
}
}
I'd hoped to be able to setup a test for Scavenger along these lines... 我希望能够按照以下方式为清道夫设置一个测试...
/// <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);
}
The issue is that (dic as IFinder) == null
. 问题是(dic as IFinder) == null
。 I know I can setup a mock class similar to Finder, or use a mocking framework, but I just want to check if I'm missing some way of casting a dictionary to do the job . 我知道我可以设置类似于Finder的模拟类,或使用模拟框架,但是我只想检查是否缺少某种铸造字典来完成这项工作的方法 。
When you have an interface and a class that implements all of the appropriate methods, but doesn't implement the interface, you can use the adaptor pattern to accopmlish your goal. 如果您有一个接口和一个实现所有适当方法的类,但没有实现该接口,则可以使用适配器模式来实现您的目标。 Create a class that implements the given interface and accepts an instance of the type that has all of the needed methods. 创建一个实现给定接口并接受具有所有必需方法的类型的实例的类。 It can then redirect all of the methods to the composed class: 然后,它可以将所有方法重定向到组成的类:
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; }
}
}
This allows you to write: 这使您可以编写:
var scavenger = new Scavenger(new DictionaryFinder(dic));
No, you cannot do that. 不,你不能那样做。 That's called duck typing and C# does not allow that. 这就是所谓的鸭子输入,而C#不允许这样做。
You can use the dynamic
keyword to accomplish this... 您可以使用dynamic
关键字来完成此任务...
Make your scavenger class like this: 使您的清除剂类如下所示:
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;
}
}
This will attempt to find the methods at runtime instead. 这将尝试在运行时查找方法。 See more at: http://msdn.microsoft.com/en-us/library/dd264741.aspx 有关更多信息,请访问: http : //msdn.microsoft.com/zh-cn/library/dd264741.aspx
You might be able to use ImpromptuInterface . 您也许可以使用ImpromptuInterface 。 I've used it to essentially do duck typing-like behavior. 我用它来做类似鸭子打字的行为。
C# does allow duck typing, to some degree, thanks to the dynamic language runtime introduced in 4.0 (I believe it was 4.0), just be very careful you don't burn yourself. 由于在4.0(我相信是4.0)中引入了动态语言运行时,因此C#确实允许在某种程度上进行鸭子类型的输入,请务必小心,不要烧伤自己。 ImpromptuInterface is proof of this. ImpromptuInterface就是证明。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.