简体   繁体   中英

C# Inheriting properties from parent interface

I'm trying to mock up a data access library for Neo4J in .NET 4.5. I am using interfaces to define each command to the database.

Given:

    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();
            }
        }

Problem is for each interface that inherits from IBaseRequest, I need a property implemented for each property that it's parent owns (HttpMethod, QueryUriSegment).

Is this possible? I know that using explicit implementation will be necessary but not sure how to push those into the implementing class.

Here is what I'd like to see in my implementing class:

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();
            }
        }
}

Notice the ICreateNode and ICreateNodeWProperties instead of the IBaseRequest. I'm open to doing it differently but it seems like a modular, testable approach.

I hope that makes sense!

You could define an abstract BaseRequest Class. That one implementing the IBaseRequest properties.

So, the classes implementing all child interfaces would inherit this BaseRequest and have the properties automatically implemented.

Forgive if I misunderstood exactly what you were looking for.

You could have a base class:

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

Then just make your TestImplClass inherit BaseNodeActions

If you want, you could also ignore using abstract and do the following:

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

If you make the properties virtual, you will only need to override the ones you actually need. You may want to remove the throwing of exceptions and make it return default values if your design allows for it.

It's not possible to do what you intend with interfaces. As you've seen, when a class implements two or more interfaces which themselves inherit a common interface, the common interface is implicitly added, but only once - you don't get a variant of the base interface for each derived interface.

You could try the following (based on the 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 ... */ }
}

In your TestImplClass you can have each command as a separate property:

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;
    }
}

Each command then has it's own HttpMethod and QueryUriSegment properties and you can mock each command and pass them into the constructor of TestImplClass when testing.

When it comes to using any of the commands you can just call Execute() on the appropriate property eg: dataAccess.CreateNode.Execute(); .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM