当“更喜欢组合而不是inheritance”时生成传递代码

问题

假设我试图将手机模型化为普通手机和PDA的组合。 这是一种多重inheritance方案(手机手机,它 PDA)。 由于C#不支持多重inheritance,因此这几乎需要某种组合。 另外,让我们说我还有其他理由支持作曲。

我一直想知道:是否有任何工具可以自动生成所有不可避免的传递代码?

让我用一些实际的代码充实我的例子:

接口:

public interface IPhone { public void MakeCall(int phoneNumber); public void AnswerCall(); public void HangUp(); } public interface IPda { public void SendEmail(string[] recipientList, string subject, string message); public int LookUpContactPhoneNumber(string contactName); public void SyncWithComputer(); } 

实现:

 public class Phone : IPhone { public void MakeCall(int phoneNumber) { // implementation } public void AnswerCall() { // implementation } public void HangUp() { // implementation } } public class Pda : IPda { public void SendEmail(string[] recipientList, string subject, string message) { // implementation } public int LookUpContactPhoneNumber(string contactName) { // implementation } public void SyncWithComputer() { // implementation } } 

CellPhone类

 public class CellPhone : IPhone, IPda { private IPhone _phone; private IPda _pda; public CellPhone(IPhone phone, IPda pda) { _phone = phone; _pda = pda; } public void MakeCall(int phoneNumber) { _phone.MakeCall(phoneNumber); } public void AnswerCall() { _phone.AnswerCall(); } public void HangUp() { _phone.HangUp(); } public void SendEmail(string[] recipientList, string subject, string message) { _pda.SendEmail(recipientList, subject, message); } public int LookUpContactPhoneNumber(string contactName) { return _pda.LookUpContactPhoneNumber(contactName); } public void SyncWithComputer() { _pda.SyncWithComputer(); } } 

编写CellPhone类很繁琐且容易出错:

所有这一课确实是作为PhonePda课程的管道。 实际上没有理由需要人工努力来输入所有这些传递语句(如_phone.MakeCall(phoneNumber); )。 它只暴露了几个成员字段的公共接口。

问题

  1. 是否有一个工具(最好是免费的:)),这将使我免于容易出错的编写传递方法的单调乏味? 我知道我可以使用VS自动生成存根,但这只能让我获得一半。

  2. 你能评价这种function的可行性和可取性吗? 是否值得向微软提出添加此类代码生成的建议? 如果我这样做,你会投票吗? 如果没有,你有什么反对意见?

编辑

每个人似乎都在说同样的话:为什么我不把_phone_pda变成公共财产? 我对此的反对意见是它违反了“最少知识原则”。 我的CellPhone类的客户端应该只做手机所做的事情,它不应该解决哪些function是Phonefunction和哪些是Pdafunction。 这会产生额外的依赖关系,并使CellPhone接口的function不那么明显。

另外,不要只关注这个例子。 如果我正在编写适配器怎么办? 它可能包含几个只是传递的接口成员,但它也可能包含一些具有唯一实现的唯一成员。 我相信在很多情况下,传递代码是一件好事 ,我只是不喜欢写它。

是的,您可以使用精彩的VS插件ReSharper生成方法

从代码生成菜单中选择“ 生成委派方法 ”选项(使用默认快捷方案的Alt-Insert)。

如果你有一个实现接口的类,包含一个实现相同接口的字段,R#将为你提供一个生成传递代码的选项。 它也可以与任意数量的接口一起使用。

我以前见过这个建议(不一定是Stack Overflow)。 不久前。 我相信作者创建了一个Connect问题,但我不知道它的状态。

建议的语法是以下之一:

 public class CellPhone : IPhone, IPda { private readonly IPhone _phone implements IPhone; private readonly IPda _pda : IPda; // ... } 

为先前提供的答案添加一些视觉效果和细节。

  1. 将接口添加到您希望成为包装类的类中

     class MyWebElement : IWebElement { } 

  1. 查找/单击“将”YouInterfaceHere“的实现委派给新字段 代表实施

  1. 选择您的选项 代表选项

  1. 点击完成并享受您的新课程

     class MyWebElement : IWebElement { private IWebElement _webElementImplementation; public IWebElement FindElement(By @by) { return _webElementImplementation.FindElement(@by); } public ReadOnlyCollection FindElements(By @by) { return _webElementImplementation.FindElements(@by); } public void Clear() { _webElementImplementation.Clear(); } public void SendKeys(string text) { _webElementImplementation.SendKeys(text); } public void Submit() { _webElementImplementation.Submit(); } public void Click() { _webElementImplementation.Click(); } public string GetAttribute(string attributeName) { return _webElementImplementation.GetAttribute(attributeName); } public string GetCssValue(string propertyName) { return _webElementImplementation.GetCssValue(propertyName); } public string TagName { get { return _webElementImplementation.TagName; } } public string Text { get { return _webElementImplementation.Text; } } public bool Enabled { get { return _webElementImplementation.Enabled; } } public bool Selected { get { return _webElementImplementation.Selected; } } public Point Location { get { return _webElementImplementation.Location; } } public Size Size { get { return _webElementImplementation.Size; } } public bool Displayed { get { return _webElementImplementation.Displayed; } } } 

您可能需要查看本文 , 该文章将进入C#中的伪多重inheritance版本。

有趣的问题。 CellPhone类是否真的可以依赖现有的具体IPhone类提供的IPhone方法的实现? 或者,CellPhone更可能需要一些支持这些方法的自定义代码?

看看你的代码(虽然我对你的要求不太了解)让我想写下这样的东西:

 public class CellPhone { private Phone _phone; private Pda _pda; public CellPhone(Phone phone, Pda pda) { _phone = phone; _pda = pda; } public IPhone getPhone() { return _phone; } public IPda getPda() { return _pda; } public void MakeCall(string contactName) { int phoneNumber = _pda.LookUpContactPhoneNumber(contactName); _phone.MakeCall(phoneNumber); } } 

问题2:

我真的不喜欢自动生成的代码。 即使机器生成它 – 并且没有错误 – 您仍将负责维护它。 那些方法看起来像是那么多噪音。