【问题标题】:Enforce getter setter access at the interface level在接口级别强制执行 getter setter 访问
【发布时间】:2016-04-24 15:50:59
【问题描述】:

我想在接口级别强制对属性的 getter 或 setter 进行访问,以便在实现它的类中遵循相同的操作。我想做如下的事情:

public interface IExample
{
    string Name
    {
        get;
        internal set;
    }
}

public class Example : IExample
{
    private string _name = String.Empty;
    string Name
    {
        get
        {
            return _name;
        }
        internal set
        {
            _name = value;
        }
    }
}

但不幸的是,据我所知,这在 C# 中是不允许的。我认为这是因为接口仅用于公开具有公共访问权限的内容(我一点也不知道!)。

我需要的是一种使用任何其他编码模式(最好使用接口)来实现它的方法,这将帮助我在其所有实现的类中强制对属性的 getter 或 setter 进行特定访问。

我用谷歌搜索了这个并试图通过 MSDN 文档来解决这个问题,但没有运气!

【问题讨论】:

  • 你不能通过接口强制执行
  • 接口不是这样工作的。它们旨在定义公共访问。为您的问题使用抽象类。
  • 没有。就我通过 google 和 docs 进行的搜索而言,界面并不意味着它是传达的内容!
  • @Mafii 这会导致数据隐藏,我认为这不是这里的意图。
  • @Mafii:这就是我之前的想法,但是除了对 getter/setter 的强制访问之外,我没有任何具体的东西可以放入抽象类中。是的,正如 Drew 所说,这会导致数据隐藏。我想要的是,任何实现接口的人都不应被允许访问已实现属性(我的意思是通过类或接口)的 getter/setter,而不是设计中允许的。

标签: c# design-patterns interface


【解决方案1】:

无论如何,在 setter 上使用 internal 有点讨厌,但如果您真的想这样做,您可以定义第二个内部接口,并将 Example internal 设置为您的程序集。

public interface IExample
{
    string Name
    {
        get;
    }
}

internal interface IExampleInternal
{
    string Name
    {
        set; get;
    }
}

internal class Example : IExample, IExampleInternal
{
    public string Name { get; set; } = string.Empty;
}

现在同一个程序集中的任何东西都可以使用IExampleInternal,而外部只能看到IExample。但是,您必须在创建的每个类上列出这两个接口。

【讨论】:

  • 这是您提供的一个非常酷的解决方案,但不幸的是它只能在程序集内部工作。我的动机是公开公开 Example 类,同时公开 IExample 接口,方法是将 Name 属性的设置器保持在内部(语言也不支持)。我知道它有点太多,但这是要求。是否有任何其他构造或设计模式可以帮助我实现这一目标?
  • 不是真的,setter 不能同时是public(接口需要)和internal。也许重新考虑一下为什么要公开公开示例:在现代基于 IOC 的应用程序中,我们通常公开一个接口并将具体实现隐藏在我们的程序集中。这样,作为这个程序集的使用者,它很容易模拟和测试,而不必同时测试两个程序集。如果您想公开它以便人们可以new 它,请考虑添加一个工厂来制作IExample 对象。
  • 我认为工厂模式是我可以尝试解决这个问题的东西。我试图了解工厂模式的工作原理。但是,如果我允许我的程序集的使用者使用程序集外部的接口 IExample 来实现和创建他自己的类,那么确保他使用属性 Name 的内部设置器的唯一方法是提供适当的文档,说明原因这是必需的,因为似乎无法在该接口的使用者上强制执行它。
【解决方案2】:

这个怎么样?这可能是一种解决方法:

// Assembly: A
public interface IExample
{
    string Name { get; }
}

// Assembly: B
using A;

public abstract class Example : IExample
{
    public string Name { get; protected internal set; }
}

public class SpecificExample : Example
{
    public void UpdateName(string name)
    {
        // Can be set because it has protected accessor
        Name = name;
    }
}

class Program
{
    static void Main(string[] args)
    {
        IExample e = new SpecificExample()
        {
            // Can be set because it has internal accessor
            Name = "OutsideAssemblyA"
        };
    }
}

// Assembly: C
using A;

public abstract class Example : IExample
{
    public string Name { get; protected internal set; }
}

public class AnotherSpecificExample : Example
{
    public void UpdateName(string name)
    {
        // Can be set because it has protected accessor
        Name = name;
    }
}

class Program
{
    static void Main(string[] args)
    {
        IExample e = new AnotherSpecificExample()
        {
            // Can be set because it has internal accessor
            Name = "OutsideAssemblyA"
        };
    }
}

这可行,但您必须在您想要创建它的特定实现的每个程序集中创建(或复制粘贴)abstract class Example,例如SpecificExampleAnotherSpecificExample

【讨论】:

  • 这将工作@Gabor,但对我来说并不是一个真正的解决方法,因为在我的场景中,抽象类部分必须由接口的实现者编写。因为在这里我将接口和实现的类作为两个独立且独立的可用单元作为我的程序集包的一部分提供,其中接口将有助于包的使用者开发一个在模式上与通过实现 IExample 接口的示例类。
  • 如果是这种情况,您只能将 XML cmets 放在您描述必须创建一个抽象类的接口上,该抽象类以 setter 受内部保护的方式实现此接口。当然,它不会强制执行任何操作,但如果将实现此接口的开发人员会看到此注释。 :)
  • 是的。这是一个很好的建议,Gabor。虽然在技术上通过代码我没有强制执行任何东西,但我可以通过文档给出明确的指导。
【解决方案3】:

这是不可能的。正如每个人都告诉你的那样,接口旨在定义公共访问。下面的代码呢?

public interface IExample
{
    string Name
    {
        get;
    }
}

【讨论】:

  • 此代码将 Name 属性的设置器的访问权限留给接口的实现者,这不是这里的意图。我希望 setter 访问是内部的或受保护的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-25
  • 2019-08-31
  • 2011-11-03
  • 1970-01-01
相关资源
最近更新 更多