0

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

所以这很容易实现,但是 API 变得有点难看,因为这个 Field 类以前在内部使用并且过于开放。例如,这只是一个小例子:IsDirty 属性不是只读的,这是最终开发人员不应该篡改的东西。

我考虑过可能创建两个接口,IPublicField 和 IPrivateField,并尝试让字段类来实现它们。但是,继续 IsDirty 示例,我不想要这样的东西:

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

Public Property IsDirty Implements IPublicField.IsDirty
 ...
End  Property

...它只是有点难看,而且您仍然可以转换回 Field 类并进入非只读方法。我也不想引入单独的 setter 方法,因为这将是另一个我不想考虑的重大更改,并且还会与 API 的其他部分产生不一致。

我最终将 Field 类重命名为 InnerField,并围绕它创建了一个外观/包装器样式结构,如下所示:

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

4 回答 4

2

在 VB.NET 的上下文中,您可以提供 IsDirty 属性范围的设置器。如果您希望程序集中的其他类可以“设置”此属性,只需将其设置为 Friend:

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

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

于 2009-02-04T22:20:49.997 回答
2

在 isDirty 属性的特定情况下,您可以只限制设置器的范围:

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.
        }
    }
于 2009-02-04T19:57:15.280 回答
1

您可以尝试使用 CAS 来发挥自己的优势。这是一个例子:

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

该属性在 System.Security 中。

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

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

于 2009-02-04T19:13:57.363 回答
1

如果您不反对使用 get 和 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

或者,如果您可以放弃 VB 并切换到 C#,则效果很好:

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
        }
    }
}
于 2009-02-04T19:19:27.977 回答