简体   繁体   English

C#接口的设计问题

[英]Design problem with C# interfaces

I have recently came to this dilemma: let's say I want to use two libraries each of them defines a interface for a consumer and a consumable: 我最近遇到了这个难题:假设我想使用两个库,每个库都为消费者和消耗品定义了一个接口:

#region Library A 
// This region represents a library (A) defining some interfaces

/// <summary>
/// Interface to be implemented by any processor of type A
/// </summary>
interface AProcessor
{
    void Process(AProcessable a);
}

/// <summary>
/// Interface to be implemented by any object processable by a processor of type A
/// </summary>
interface AProcessable
{
    int MyPropertyA { get; set; }
}
#endregion


#region Library B
// This region represents a library (B) defining some other interfaces

/// <summary>
/// Interface to be implemented by any processor of type B
/// </summary>
interface BProcessor
{
    void Process(BProcessable a);
}

/// <summary>
/// Interface to be implemented by any object processable by a processor of type B
/// </summary>
interface BProcessable
{
    int MyPropertyB { get; set; }
}
#endregion

Then, on my application, I implement a consumable type that implements both consumable interfaces from each library: 然后,在我的应用程序上,实现一个可消耗类型,该类型实现每个库中的两个可消耗接口:

/// <summary>
/// A type processable by processors of type A and processors of type B.
/// </summary>
class Processable :
    AProcessable,
    BProcessable
{
    // Implements interface AProcessable
    public int MyPropertyA { get; set; }

    // Implements interface BProcessable
    public int MyPropertyB { get; set; }
}

And I implement a consumer type capable of consume objects of type Processable, which implements AProcessable and BProcessable: 我实现了一个消费者类型,该消费者类型能够使用可处理类型的对象,该对象将实现AProcessable和BProcessable:

/// <summary>
/// A processor that implements an A-type processor and a B-type processor.
/// </summary>
class Processor : 
    AProcessor, 
    BProcessor
{
    // I thought that Process method would implement AProcessor.Process() and
    // BProcessor.Process() as it expects a Processable object as parameter which
    // implements AProcessable and BProcessable, but it doesn't.
    // Compiler rises an error telling that Processor doesn't implement neither
    // AProcessor.Process() nor BProcessor.Process()
    /*
    public void Process(Processable a)
    {
        throw new NotImplementedException();
    }
    */


    // Implementing both methods does not work because it creates ambiguity: when
    // we call Processor.Process(p) being "p" a Processable object the compiler 
    // doesn't know if it has to call Processor.Process(AProcessable) or
    // Processor.Process(BProcessable).
    /*
    public void Process(AProcessable a)
    {
        throw new NotImplementedException();
    }

    public void Process(BProcessable a)
    {
        throw new NotImplementedException();
    }
    */
}

¿What's my design error and what would be the correct approach? ¿我的设计错误是什么?正确的方法是什么?

Thanks in advance. 提前致谢。

You are looking for Explicit Interface implementations. 您正在寻找显式接口实现。 This link has a tutorial: 此链接包含一个教程:

http://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx http://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx

Basically, the method signature shows the interface type: 基本上,方法签名显示接口类型:

void BProcessor.Process(BProcessable b)
{

}

And can only be accessed with a direct reference to BProcessor : 并且只能通过直接引用BProcessor来访问:

BProcessor b;
b.Process(null);

An inferred reference to BProcessor will not work with explicit implementations: BProcessor的推断引用不适用于显式实现:

Processor p;
p.Process(new BProcessable()); // This won't compile.

This allows you to implement interfaces that have conflicting member names. 这使您可以实现具有冲突成员名称的接口。 If they have conflicting type names, you then need to start looking into namespace conflicts. 如果它们的类型名称冲突,则需要开始研究名称空间冲突。

You'll notice an explicit implementation because when you get Intellisense for Processor it will be missing Process(BProcessable b) . 您会注意到一个明确的实现,因为当您获得Intellisense for Processor ,它将丢失Process(BProcessable b)

If your code for handling process happens to be shared, you can do the following: 如果您的处理代码恰好是共享的,则可以执行以下操作:

public void Process(Processable p)
{

}

void AProcess.Process(AProcessable a)
{
    Process((Processable)a);
}

void BProcess.Process(BProcessable b)
{
    Process((Processable)b);
}

However, personally I'd avoid this type of forward casting as you aren't guaranteed (other than you being in full control of the code) to get given a Processable type. 不过,我个人会避免这种类型的前锋铸造的,你不能保证得到赋予了(比你在代码的完全控制是其他) Processable类型。

Use explicit interface implementations: 使用显式接口实现:

void AProcessor.Process(AProcessable a)
{
    throw new NotImplementedException();
}

void BProcessor.Process(BProcessable a)
{
    throw new NotImplementedException();
}

Using explicit interface implementations disable automatic lookup of what method to call. 使用显式接口实现会禁用自动查找要调用的方法。 When you call those methods you need to cast the object to an interface: 调用这些方法时,需要将对象强制转换为接口:

Processor p;
Processable pa;
((AProcess)p).Process(pa);

Except for handling this situation with conflicting names/method signatures explicit implementations can also be used to hide (or at least make it harder to use) methods that are required by an interface, but isn't making sense for a specific class. 除了用冲突的名称/方法签名来处理这种情况外,显式实现还可以用于隐藏(或至少使其难于使用)接口所需的方法,但对于特定类而言这是没有意义的。

I don't think that explicit interface implementation is needed here, since there is no collision between the signatures of the two processing methods (the type of the argument is AProcessable for AProcessor and BProcessable for the second). 我认为这里不需要显式接口实现,因为两种处理方法的签名之间没有冲突(参数的类型对于AProcessor是AProcessable,对于第二个是BProcessable)。 Since I immagine that for Processable instances you want both the processing to be executed, I would implement it this way: 既然我想像一下,对于可处理实例,您希望两个处理都执行,那么我可以这样实现:

public class Processor : AProcessor, BProcessor
{
    #region AProcessor Members

    public void Process(AProcessable a)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    #endregion

    #region BProcessor Members

    public void Process(BProcessable a)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    #endregion

    public void Process(Processable a)
    {
        Process((AProcessable)a);
        Process((BProcessable)a);
    }
}

In your first attempt, with one method, you are not implementing the precise definition form the interface, which does not want a Processable object as a parameter, but an AProcessable and BProcessable, depending on which one you want. 首次尝试使用一种方法时,您不是在接口上实现精确的定义,该接口不希望将Processable对象作为参数,而是要使用AProcessable和BProcessable,具体取决于所需的接口。

The second, as others have pointed out, needs to use explicit implementations, so that you can clearly define which of the two you want to call. 正如其他人指出的那样,第二个需要使用显式实现,以便您可以清楚地定义要调用的两个。

If you want to call both of them, then you need to make two separate calls - you could implement a method Process wihtin the class, and call AProcessable.Process and BProcessable.Process. 如果要调用它们两者,则需要进行两个单独的调用-您可以在类中实现一个Process方法,然后调用AProcessable.Process和BProcessable.Process。 But it has to be done explicitly, not just through inheritance and interfaces. 但这必须显式完成,而不仅仅是通过继承和接口。

Everyone has provided fine explainations for the technical reasons why the code isn't working, however I assume you understand these as your question asked what the design issue is and how to solve it.... so I'll add my 2c into the mix. 每个人都为代码无法工作的技术原因提供了很好的解释,但是我想您理解这些,因为您的问题是什么是设计问题以及如何解决...。因此,我将2c添加到混合。

Basically you are trying to two mix two otherwise completely distinct concepts into one logical controlling piece of code (the Processor class). 基本上,您试图将两个完全不同的概念混合到一个逻辑控制代码中(Processor类)。

By defining two different things that can be processed and two means by which processors of those things must behave you are setting about defining a system that processes two distinct things in completely different ways... therefore they are not the same and can't be combined. 通过定义两个可以处理的不同事物以及这些事物的处理器必须以两种方式运行,您正在着手定义一个系统,该系统以完全不同的方式处理两个不同的事物……因此,它们是不一样的,不能相同。结合。

As for another solution on how to "fix" the problem (I use the word fix lightly as it's hard to suggest an alternate solution without knowing the context of the problem you solving) you really need to find a way to represent the two processable types and processors in a common way.... or just not mix the two concepts in the concrete Processor implementation. 至于关于如何“解决”问题的另一种解决方案(我轻率地使用“修复”一词,因为在不知道您要解决的问题的背景下很难提出替代解决方案),您确实需要找到一种方法来表示两种可处理类型和处理器以一种通用的方式...。或者只是在具体的处理器实现中不将这两个概念混合在一起。

Knowing more about the actual context of the problem would help us give a more accurate suggestion! 进一步了解问题的实际背景将有助于我们给出更准确的建议! :) :)

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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