繁体   English   中英

尝试在基抽象类中使用受保护的构造函数并将注入的接口标记为内部时出现不一致的可访问性错误

[英]Getting inconsistent accessibility error while trying to have protected constructor in base abstract class with interface injected marked as internal

我有 1 个接口 IMetadata,我想限制对当前程序集(类库)的访问,而不是在它之外,因此我将其标记为内部。

现在我想把这个接口注入到我的基抽象类中,并在我的基类方法上调用 IMetadata 的方法来执行一些逻辑。 例如,基类将从派生类 Type1 接收版本控制,因此我已将基抽象类构造函数标记为受保护,但出现以下错误:

不一致的可访问性:参数类型 IMetadata 的可访问性低于 BaseType.BaseType(IMetadata)

但是这个元数据总是会从派生类(Type1)接收它的具体类型,因此我希望这个基类构造函数受到保护,并且我希望元数据只在当前程序集中可用,而不是在它之外。

internal interface IMetadata
{
   string CreateMetadata();
}

internal class Metadata : IMetadata
{
    public Metadata(string location)
    {       
          this.location = location;   
    }
    public string CreateMetadata()
    {
    }
}

public interface IBaseType
{ 
    Void Perform();
} 

public abstract class BaseType : IBaseType
{
   private readonly IMetadata _metadata;
   protected BaseType(IMetadata metadata) //error
   {

   }
}

class Type1 : BaseType
{
    public Type1(IMetadata metadata) : 
    base(metadata)
    {
    }
}

谁能告诉我问题是什么以及如何实现这种封装?

编译器执行这些可访问性检查的原因是试图引导您进入“成功之坑” 您将“东西”标记为(或允许默认)为internal 这意味着它是程序集中的一个实现细节 程序集之外的任何东西都不应该知道或关心这个“东西”是什么。 它当然无法“说出它的名字”或创建一个。

然后你写一些publicprotected 这些东西给其他组件可见。 然后你说“为了使用它,你必须提供一个东西”。 你泄露了一个实现细节,这就是编译器阻止你的原因。 您需要仔细研究这一点,并决定它不是纯粹的实现细节(因此将其public ),或者您不应该将它暴露在程序集之外。

理想情况下,您将此构造函数标记为带有正确语义的private protected - 只有{从此类继承的类}和{此程序集中的类}的交集才能调用它。 无论如何,只有程序集的其他成员才能获得所需的实例。

但是,如果您还没有使用 C#7.2,则必须做出选择。 我会选择internal 无论如何,它是一个抽象类,即使使用理论上与继承层次结构无关的构造函数,也没有人可以直接构造它。


这编译得很好并显示了两种方法:

internal interface IMetadata
{
  string CreateMetadata();
}

internal class Metadata : IMetadata
{
  private readonly string location;
  public Metadata(string location)
  {
    this.location = location;
  }
  public string CreateMetadata()
  {
    return string.Empty;
  }
}

public interface IBaseType
{
  void Perform();
}

public abstract class BaseType : IBaseType
{
  private readonly IMetadata _metadata;
  private protected BaseType(IMetadata metadata) //No error
  {

  }

  internal BaseType(IMetadata metadata, int thing) //No error
  {

  }

  public abstract void Perform();
}

class Type1 : BaseType
{
  public Type1(IMetadata metadata) :
  base(metadata)
  {
  }

  public Type1(IMetadata metadata, int thing) : base(metadata, thing)
  {

  }

  public override void Perform()
  {
    throw new NotImplementedException();
  }
}

暂无
暂无

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

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