代码之家  ›  专栏  ›  技术社区  ›  Brian MacKay

有趣的API设计/模式

  •  0
  • Brian MacKay  · 技术社区  · 16 年前

    我正在重新设计内部ORM工具的一部分,我想直接向最终开发人员公开Field(一个表示数据库中字段的类,比如CustomerFirstName)。

    我考虑过创建两个接口,IPublicField和IPrivateField,并尝试让field类实现这两个接口。但是,继续以IsDirty为例,我不希望出现这样的情况:

    Public ReadOnly Property PrivateIsDirty Implements IPrivateField.IsDirty
     ...
    End  Property
    
    Public Property IsDirty Implements IPublicField.IsDirty
     ...
    End  Property
    

    最后,我将Field类重命名为InnerField,并围绕它创建了一个facade/wrapper样式的结构,如下所示:

    Public Class Field
        Implements BusinessObjects.IField
    
        Private InnerField As BusinessObjects.IInnerField
    
        Public Sub New(ByVal field As IInnerField)
            InnerField = field
        End Sub
    
        ...
    
         Public ReadOnly Property IsDirty() As Boolean Implements BusinessObjects.IField.IsDirty
            Get
                Return InnerField.IsDirty
            End Get
        End Property
    
        ...
    End Class
    

    看来效果不错。在内部,InnerField是适当开放的,我们可以在不影响最终开发人员的情况下,在将来使其更加开放,而在外部,Field类提供了最终开发人员需要的简化、锁定的工具。

    谢谢!

    4 回复  |  直到 9 年前
        1
  •  2
  •   GWLlosa    16 年前

    在isDirty属性的特定情况下,您可以限制setter的范围:

    public bool IsDirty
         {
            get
            {
                // logic here that the end-devs can use safely.
            }
            private set
            {
                // logic here that is only exposed to other members of your private
                // ORM assembly.
            }
        }
    
        2
  •  2
  •   HardCode    16 年前

    Public Property IsDirty() As Boolean
        Get
            Return _isDirty
        End Get
        Friend Set(ByVal trueFalse As Boolean)
            _isDirty = trueFalse
        End Set
    End  Property
    

    现在,任何外部程序集都可以检查IsDirty属性,但只有同一程序集中的类才能设置它。

        3
  •  1
  •   Jonathan C Dickinson    16 年前

    你可以的 利用你的CAS。下面是一个例子:

        public bool IsDirty
        {
            get;
            [StrongNameIdentityPermissionAttribute(SecurityAction.LinkDemand, Name = "<assembly name>")]
            set;
        }
    

    如果您担心您的开发人员可能会通过反射调用LinkDemand,那么您可能需要将LinkDemand更改为Demand:但是您也可以“替换”这些开发人员,而不是SecurityAction:)。

    唯一的问题是现在你在运行时有了检查。这可能不是你想要的,但如果没有重大的重组努力,我看不出它还能以其他方式运作。

        4
  •  1
  •   Michael Meadows    16 年前

    如果您不反对使用get and set方法而不是属性,请尝试让IPublicField实现IPrivateField。

    Public Interface IPrivateField
        Function GetDirty() As Boolean
    End Interface
    
    Public Interface IPublicField
        Inherits IPrivateField
    
        Sub SetDirty(ByVal dirty As Boolean)
    End Interface
    
    Public Class Whatever
        Implements IPublicField
    
        Public Function GetDirty() As Boolean Implements IPrivateField.GetDirty
            ' logic here
        End Function
    
        Public Sub SetDirty(ByVal dirty As Boolean) Implements IPublicField.SetIsDirty
            ' logic here
        End Sub
    End Class
    

    public interface IPrivateField
    {
        bool IsDirty { get;}
    }
    
    public interface IPublicField : IPrivateField
    {
        new bool IsDirty { get; set; }
    }
    
    public class Whatever : IPublicField
    {
        public bool IsDirty 
        {
            get
            {
                // logic here
            }
            set
            {
                // logic here
            }
        }
    }