0

我正在尝试创建一个代码重复最少的高效类。

我有这个定义:

Public Class Foo
    Private _firstName as string = ""
    Private _lastName as string = ""

    Public Sub New(ByVal userGUID As Guid)
        'query DB to get firstName and lastName
        Me.New(dt.Rows(0)("FirstName").ToString(),dt.Rows(0)("LastName").ToString())
    End Sub

    Public Sub New(ByVal firstName As String, ByVal lastName As String)
        _firstName = firstName.toUpper()
        _lastName = lastName.toUpper()
        Validate()
    End Sub

    Private Sub Validate()
        ' Throw error if something is wrong
    End Sub
End Class

具有 firstName 和 lastName 参数的构造函数是进行验证的端点构造函数。以 userGUID 作为参数的构造函数将查询 DB 以获取名称并调用最终构造函数。这样,所有执行都应该针对实际执行所有验证等的构造函数之一。其背后的想法是,如果我添加新的构造函数,我只需要提取必要的数据(名字/姓氏)并调用最终的构造函数进行验证。

但是,有一个编译错误阻止我在线使用这个系统Me.New(dt.Rows(0)("FirstName").ToString(),dt.Rows(0)("LastName").ToString())。显然,这一行必须是构造函数中的第一行。但是如果我将其作为第一行,它将破坏验证过程,因为验证会由于没有名字/姓氏而引发错误。我必须查询数据库才能提取该信息。

我知道我可以在这里分配值并从这个构造函数调用验证,但这会有效地将这个构造函数与最后一个构造函数隔离,从而复制代码并增加维护。仅供参考,在下面的示例中,我只有 2 个构造函数,但实际上我还有更多。如果每个人都会做自己的任务,那么它只会增加维护。

那么,有没有办法通过执行一些代码然后调用重载的构造函数来完成我的任务?

感谢您的任何见解

更新 1:

根据 the_lotus 评论,我包括 dt 定义。这个问题有一个解决方法。基本上我会从最终的构造函数中取出验证和赋值,并将其放入一个函数中。所有的构造函数都会调用这个函数,从而消除了链接构造函数的需要。它看起来不错,但我想了解为什么为了链接构造函数,我必须将构造函数调用放在第一行。

这是新代码:

公共类 Foo Private _firstName As String = "" Private _lastName As String = ""

Public Sub New(ByVal userGUID As Guid)
    Dim dt As New DataTable
    ' query DB to get firstName and lastName
    ' Assume I populate dt with at least one DataRow
    AssignAndValidate(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString())
    'Me.New(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString())
End Sub

Public Sub New(ByVal firstName As String, ByVal lastName As String)
    AssignAndValidate(firstName, lastName)
End Sub

Private Sub Validate()
    ' Throw error if something is wrong
End Sub

Private Sub AssignAndValidate(ByVal firstName As String, ByVal lastName As String)
    _firstName = firstName.ToUpper()
    _lastName = lastName.ToUpper()
    Validate()
End Sub

结束类

一个奇怪的更不用说:在线代码转换器(vb.net 到 C#)在转换链式构造函数调用时没有问题,而不是在第一行。C# 代码返回为this.#ctor(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString());但是,如果我尝试转换回 VB.NET,它会失败。

4

2 回答 2

3

您正在寻找的是工厂方法

Public Class Foo 

    Public Shared Function GetFooFromGuid(ByVal userGUID As Guid) As Foo

        ' Query db

        return New Foo(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString())
    End Function

End Class

或者一个初始化函数

Public Class Foo 

    Public Sub New(ByVal userGUID As Guid)
        ' query DB to get firstName and lastName
        Initialize(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString())
    End Sub

    Public Sub New(ByVal firstName As String, ByVal lastName As String)
        Initialize(firstName, lastName)
    End Sub

    Private Sub Initialize(ByVal firstName As String, ByVal lastName As String)
    End Sub

End Class

就个人而言,我不会在 New 中调用数据库。

于 2015-05-11T17:02:18.130 回答
0

我不喜欢的是您在构造函数上访问数据库,以及在构造函数中验证。我认为这是设计问题。下面是 3 个重载构造函数的示例。所有三个工作。你可能需要#3。dt以静态(vb - 共享)方法初始化您的。您还可以将 fname/lname 参数替换为包含两者的参数。这将适用于您的#3

public class A
{
    public A() : this ("xxx")
    {

    }
    public A(string x)
    {

    }
}

public class A
{
    public A() 
    {

    }
    public A(string x): this ()
    {

    }
}

public class A
{
    public A() : this(GetXxx())
    {

    }
    public A(string x)
    {

    }

    private static string GetXxx()
    {
        return "xxx";
    }
}

为什么要构造函数链?因为您的对象可以在许多属性中具有默认值,并且您可能有许多构造函数,每个构造函数都添加一个属性。在内部,一个构造函数可以设置 5 个属性,而其他 4 个构造函数只能设置 1 个属性。

例如:

public class Door
{
    private string _material = "wood";
    private int _locks = 1;
    private int _hinges = 3;

    public Door()
    {

    }
    public Door(int locks) : this()
    {
        _locks = locks;
    }
    public Door(int locks, int hinges) : this(locks)
    {
        _hinges = hinges;
    }
}
于 2015-05-11T16:13:42.717 回答