根据界面强制输入

时间:2018-06-20 12:04:10

标签: c# interface polymorphism abstract-class

我有一个抽象类,它强制实现方法,该方法将接口作为输入,如下所示:

public abstract DocumentWriter
{
    (...)
    protected abstract void FillContent(IDocumentArgs args);
}

创建接口IDocumentArgs是为了确保某些参数包含在参数中,否则该接口很大程度上取决于DocumentWriter的实现。

public interface IDocumentArgs
{
    string Title { get; set; }
    string Subject { get; set; }
    string Author { get; set; }
}

基于此接口,我实现了此接口的实现,该接口将在DocumentWriter的实现中使用。看起来像这样:

public class ActualDocumentArgs : IDocumentArgs
{
    // Properties enforced by the interface
    string Title { get; set; }
    string Subject { get; set; }
    string Author { get; set; }

    // Custom properties
    string CustomerName { get; set; }
    DateTime DueDate { get; set; }
    (...)
}

问题是:我想使用FillContent()实现ActualDocumentArgs(我想应该可以实现,因为它实现了IDocumentArgs),就像这样:

public class ActualDocumentWriter : DocumentWriter
{
    (...)    
    protected override void FillContent(ActualDocumentArgs args)
    {
        // Do stuff
    }
}

但是,如果执行此操作,则会出现编译时错误:

  

'ActualDocumentWriter.FillContent(ActualDocumentArgs)':找不到合适的方法来覆盖。

另一方面,我不能使用IDocumentArgs作为输入,因为那样我将无法访问自定义属性。

如何解决这个问题?这让我头疼...

3 个答案:

答案 0 :(得分:1)

您可以使用generic constraint

public abstract DocumentWriter<T>
  where T : IDocumentArgs
{
    (...)
    protected abstract void FillContent(T args);
}

public class ActualDocumentWriter : DocumentWriter<ActualDocumentArgs>
{
    (...)    
    protected override void FillContent(ActualDocumentArgs args)
    {
        // Do stuff
    }
}

答案 1 :(得分:1)

您当前的抽象类要求该方法接受实现IDocumentArgs的所有内容。您可以 检查传入的类型,但是编译器本身不会强制执行。

您可以做的一件事是将抽象类更改为通用类。像这样:

public abstract class DocumentWriter<T> where T : IDocumentArgs
{
    protected abstract void FillContent(T args);
}

请注意类型参数上的where约束,要求实现类型仅将IDocumentArgs的派生类型用作类型参数。

然后在实现该类时,显式提供type参数:

public class ActualDocumentWriter : DocumentWriter<ActualDocumentArgs>
{ 
    protected override void FillContent(ActualDocumentArgs args)
    {
        // Do stuff
    }
}

答案 2 :(得分:-1)

  

我不能使用IDocumentArgs作为输入,因为那样我将无法访问自定义属性。

表示设计错误。 你不应该这样。

您可以规避它,在覆盖方法内可以强制转换它:

protected override void FillContent(IDocumentArgs args)
{
    var actualArgs = args as ActualDocumentArgs ;
    // Do stuff
}

但这是黑客。