【问题标题】:C# Inheriting properties from parent interfaceC#从父接口继承属性
【发布时间】:2013-05-24 19:23:47
【问题描述】:

我正在尝试在 .NET 4.5 中模拟 Neo4J 的数据访问库。我正在使用接口来定义数据库的每个命令。

给定:

    public interface IBaseRequest 
    {
        HttpMethod HttpMethod { get; }    
        string QueryUriSegment { get; }    
    }

    public interface ICreateNode  : IBaseRequest
    {
        void CreateNode();

    }

    public interface IBaseNodeActions  : ICreateNode,ICreateNodeWProperties //...And many others, all inherit from IBaseRequest
    {
    }

    internal class TestImplClass : IBaseNodeActions {


        public TestImplClass() {


        }
        void ICreateNode.CreateNode() {
            throw new NotImplementedException();
        }
        //Only one copy of the HttpMethod and QueryUriSegment are able to be implemented
        DataCommands.HttpHelper.HttpMethod IBaseRequest.HttpMethod {
            get {
                throw new NotImplementedException();
            }
        }

        string IBaseRequest.QueryUriSegment {
            get {
                throw new NotImplementedException();
            }
        }

问题在于从 IBaseRequest 继承的每个接口,我需要为其父级拥有的每个属性(HttpMethod、QueryUriSegment)实现一个属性。

这可能吗?我知道使用显式实现是必要的,但不确定如何将它们推送到实现类中。

这是我希望在我的实现类中看到的内容:

public class TestImplClass : IBaseNodeActions{
public TestImplClass() {


        }
        void ICreateNode.CreateNode() {
            throw new NotImplementedException();
        }

        HttpMethod ICreateNode.HttpMethod {
            get {
                throw new NotImplementedException();
            }
        }

        string ICreateNode.QueryUriSegment {
            get {
                throw new NotImplementedException();
            }
        }
        HttpMethod ICreateNodeWProperties.HttpMethod {
            get {
                throw new NotImplementedException();
            }
        }

        string ICreateNodeWProperties.QueryUriSegment {
            get {
                throw new NotImplementedException();
            }
        }
}

注意 ICreateNode 和 ICreateNodeWProperties 而不是 IBaseRequest。我愿意采取不同的做法,但这似乎是一种模块化、可测试的方法。

我希望这是有道理的!

【问题讨论】:

  • 我不明白你想要什么。您的测试类是否实现了所有接口???如果是这样,您希望属性根据您调用的接口给出不同的结果吗?
  • 或者想要避免多次实现这些属性???如果是这样,请不要显式地实现这些属性。

标签: c# .net inheritance interface


【解决方案1】:

不可能用接口做你想做的事。如您所见,当一个类实现了两个或多个本身继承一个公共接口的接口时,该公共接口被隐式添加,但只添加一次 - 您不会为每个派生接口获得基接口的变体。

您可以尝试以下方法(基于Command pattern):

interface ICommand {
    HttpMethod HttpMethod { get; }    
    string QueryUriSegment { get; }

    void Execute();
}

class abstract BaseCommand : ICommand {
    public abstract HttMethod { get; }
    public abstract string QueryUriSegment { get; }
}

class CreateNodeCommand : ICommand {
    public override HttpMethod HttpMethod { get { /* return HttpMethod for "create node" */ } }
    public override string QueryUriSegment { get { /* return QueryUriString for "create node" */ } }

    public void Execute() { /* Create node... */ }
}

class CreateNodeWithPropertiesCommand : ICommand {
    public override HttpMethod HttpMethod { get { /* return HttpMethod for "create node with properties" */} }
    public override string QueryUriSegment { get { /* return QueryUriString for "create node with properties" */ } }

    public void Execute() { /* Create node with properties ... */ }
}

在您的 TestImplClass 中,您可以将每个命令作为单独的属性:

public TestImplClass {
    public ICommand CreateNode { get; private set; }
    public ICommand CreateNodeWithProperties { get; private set; }

    public TestImplClass(ICommand createNode, ICommand createNodeWithProperties) {
        this.CreateNode = createNode;
        this.CreateNodeWithProperties = createNodeWithProperties;
    }
}

然后每个命令都有自己的 HttpMethod 和 QueryUriSegment 属性,您可以模拟每个命令并在测试时将它们传递给 TestImplClass 的构造函数。

在使用任何命令时,您只需在适当的属性上调用 Execute(),例如:dataAccess.CreateNode.Execute();

【讨论】:

  • 我可以看到这种方法在我的情况下是如何工作的。如果您注意到我的代码,它正在处理“节点”命令。然而,我试图以这种方式设计它的原因是为了容纳至少 3 个使用相同模式的其他命令的其他层次结构。你会建议我在哪里分支这个设计来构建这些新的实现?
  • 您能否详细说明命令层次结构的含义?
  • 还有其他与节点无关的接口从我的示例中继承了相同的父 IBaseRequest。然后会有另一个接口将它们组合成 IBaseRelationshipActions 作为示例。
  • 您可以按照最初的意图进行操作,并将命令分组在界面中。您可能会发现使用太多命令时,构造函数变得无法维护或至少难以使用。另一种方法是创建单个数据访问类,并将操作实现为方法,例如:CreateNode(Node node)CreateNode(Node node, object parameters)。正确完成这不会影响可测试性。
  • 嗨 Talon,我正在使用命令模式根据您的建议重新处理我的 UML 图。问题:在上面的代码中,您是否打算使用 CreateNodeCommand : BaseCommand 而不是 CreateNodeCommand : ICommand?看来这就是你的意图。谢谢顺便说一句!
【解决方案2】:

您可以定义一个抽象的 BaseRequest 类。 实现IBaseRequest 属性的那个。

因此,实现所有子接口的类将继承此 BaseRequest 并自动实现属性。

【讨论】:

    【解决方案3】:

    如果我误解了您要查找的内容,请原谅。

    你可以有一个基类:

    public abstract class BaseNodeActions : IBaseNodeActions
    {
        public abstract void CreateNode();
        public abstract HttpMethod HttpMethod {get;set;}
        ....
    }
    

    那就让你的TestImplClass继承BaseNodeActions

    如果你愿意,你也可以忽略使用 abstract 并执行以下操作:

    public class BaseNodeActions : IBaseNodeActions
    {
        public virtual void CreateNode() { throw new NotImplementedException(); }
        public virtual HttpMethod HttpMethod {get { throw new NotImplementedException(); }
        ....
    }
    

    如果您将属性设为虚拟,则只需覆盖您实际需要的属性。如果您的设计允许,您可能希望删除抛出异常并使其返回默认值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 2017-05-12
      • 2012-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多