部分封装字段C#

部分封装字段C#,c#,design-patterns,C#,Design Patterns,我想知道是否有任何模式可以克服这个问题: 我有一组属性需要对几个类公开,而对其他类则应该是只读的, 类必须是公共类 我不想使用反射或任何其他糟糕的性能制造者 我知道我可以让它们反渗透,并在类内实现逻辑,但我认为这并不好 有什么帮助吗?两个选项: 将属性设置为内部(而不是类),并将类分组到不同的程序集中 使用反射魔法 遗憾的是,C#中没有friend类。在当前程序集中,您可以将其设置为内部 在当前程序集之外,最好通过[InternalsVisibleTo]将其提供给特定程序集 .NET不提供更细粒

我想知道是否有任何模式可以克服这个问题: 我有一组属性需要对几个类公开,而对其他类则应该是只读的, 类必须是公共类

我不想使用反射或任何其他糟糕的性能制造者

我知道我可以让它们反渗透,并在类内实现逻辑,但我认为这并不好

有什么帮助吗?

两个选项:

  • 将属性设置为内部(而不是类),并将类分组到不同的程序集中
  • 使用反射魔法

  • 遗憾的是,C#中没有
    friend
    类。

    在当前程序集中,您可以将其设置为
    内部

    在当前程序集之外,最好通过
    [InternalsVisibleTo]
    将其提供给特定程序集

    .NET不提供更细粒度的“朋友”访问


    对于那些应该进行r/o访问的类-使用
    IReAdolTyperson

    ,您可以尝试在基类中将setter声明为受保护。任何派生它的类都可以设置它。但是任何使用派生类的类都只能看到只读属性

    public class ClassBase
    {
        public int MyProperty
        {
            get;
            protected set;
        }
    }
    
    public sealed class ClassDerived : ClassBase
    {
        public ClassDerived()
        {
            MyProperty = 4; // will set
        }
    }
    
    public class ClassUsingDerived
    {
        public ClassUsingDerived()
        {
            ClassDerived drv = new ClassDerived();
            drv.MyProperty = 5; // will fail
        }
    }
    

    如果我理解正确的话:)

    我认为这应该被视为一种反模式。我同意约翰的观点。事实上,我认为如果您想为不同的呼叫者提供不同的成员可访问性,那么您在设计上就有问题。NET lackes细粒度好的朋友。非常有效的积分;实际上,我通常只在单元测试中使用[InternalsVisibleTo]。@Johannes——我不同意。我可以想出几个很好的理由来这样做,尽管我通常会将InternalsVisible的使用限制为仅用于测试程序集。它允许使用工厂(在同一程序集中)访问属性设置程序,同时保留属性的只读性质,在对应用程序的DB进行集成工作时,几乎需要通过严格定义设计器生成的类中可以在数据层之外发生的交互类型来安全地添加功能。我们为单元测试做了很多事情,但对生产代码却不会做,是吗?(想想所有的反射等)我认为[nimulsVistiButo ]对单元测试是很好的。这就是我没有投反对票的原因。只有当所讨论的类是派生类时,这才有效。当消费者不是衍生产品时会发生什么?我认为这是他的真正问题。
    public class ClassBase
    {
        public int MyProperty
        {
            get;
            protected set;
        }
    }
    
    public sealed class ClassDerived : ClassBase
    {
        public ClassDerived()
        {
            MyProperty = 4; // will set
        }
    }
    
    public class ClassUsingDerived
    {
        public ClassUsingDerived()
        {
            ClassDerived drv = new ClassDerived();
            drv.MyProperty = 5; // will fail
        }
    }