2016-04-05 89 views
2

我很尷尬以分享此功能,但我需要幫助它整齊。我很久以前寫了這個非常簡單的使用方法,但它已經失控,我不知道如何正確處理它。處理大量的可選參數

Public Shared Function SetVariables(msg As String, Optional name As String = "", Optional target As String = "", Optional amount As Decimal = 0, Optional cost As String = "0", Optional keyword As String = "", Optional time As String = "", Optional reward As String = "", Optional participantList As String = "", Optional participantCount As Integer = 0, Optional game As String = "", Optional viewers As String = "", Optional followers As String = "", Optional link As String = "", Optional _options As String = "", Optional Year As String = "", Optional Month As String = "", Optional Day As String = "", Optional Hour As String = "", Optional Minute As String = "", Optional grpname As String = "") 
    Dim balance As Decimal 
    Dim holdings As Decimal 
    If name > "" Then 
     If Options.Accounts.ContainsKey(name) Then 
      If Options.Holdings.ContainsKey(Options.Accounts.Item(name)) Then 
       holdings = Options.Holdings.Item(Options.Accounts.Item(name)) 
      End If 
      balance = Options.Accounts.Item(name).Points 
     End If 
    End If 
    msg = msg.Replace("[name]", StrConv(name, VbStrConv.ProperCase)) 
    If holdings > 0 Then 
     msg = msg.Replace("[balance]", balance & "[" & holdings & "]") 
    Else 
     msg = msg.Replace("[balance]", balance) 
    End If 
    msg = msg.Replace("[channel]", Subs.UppercaseFirstLetter(Options.Channel.TrimStart("#"))) 
    msg = msg.Replace("[target]", Subs.UppercaseFirstLetter(target)) 
    msg = msg.Replace("[amount]", amount) 
    msg = msg.Replace("[cost]", cost) 
    msg = msg.Replace("[keyword]", keyword) 
    msg = msg.Replace("[time]", time) 
    msg = msg.Replace("[reward]", reward) 
    msg = msg.Replace("[participantList]", participantList) 
    msg = msg.Replace("[participantCount]", participantCount) 
    msg = msg.Replace("[botname]", Subs.UppercaseFirstLetter(Options.User)) 
    If msg.Contains("[groups]") Then msg = msg.Replace("[groups]", GetSortedGroups(name)) 
    If msg.Contains("[group]") Then msg = msg.Replace("[group]", GetSortedGroups(name, True)) 
    msg = msg.Replace("[game]", StrConv(game, VbStrConv.ProperCase)) 
    msg = msg.Replace("[viewers]", viewers) 
    msg = msg.Replace("[followers]", followers) 
    msg = msg.Replace("[link]", link) 
    msg = msg.Replace("[options]", options.ToUpper) 
    msg = msg.Replace("[years]", Year) 
    msg = msg.Replace("[months]", Month) 
    msg = msg.Replace("[days]", Day) 
    msg = msg.Replace("[hours]", Hour) 
    msg = msg.Replace("[minutes]", Minute) 
    msg = msg.Replace("[grpname]", StrConv(grpname, VbStrConv.ProperCase)) 

    If balance = 1 Or amount = 1 Then 
     msg = msg.Replace("[currency]", Options.PName) 
    Else 
     msg = msg.Replace("[currency]", Options.PNames) 
    End If 
    Return msg 
End Function 

基本上我把一個字符串傳遞給這個函數,它包含了一些這樣的:[name] [keyword]等,用其他的替換。有時候我也必須傳遞數據來替換這些數據,這就是問題出現的地方。我想要這些功能,但我現在有很多參數。我從不在函數的單個調用中使用所有這些參數,隨着時間的推移,我將增加更多的參數。

有關如何更好地處理這樣的事情的任何意見?我是否應該將這個功能拆開,並根據個人情況處理替換件?

+3

由這些參數組成的課程應使其更簡潔 – Plutonix

+0

您可能是對的。我實際上想過這樣做,並忘記了這個想法。謝謝! – Josh

+0

@Plutonix使用我在OP中共享的內容,你能夠寫出一個粗略的例子來說明你將如何構建這個類?它仍然覺得我在使用這個課程時會有很長的字符串,但也許我看錯了。 – Josh

回答

1

你這樣做的方式非常昂貴。 Strings是不變的,所以這樣一行:

msg = msg.Replace("[followers]", followers) 

...撕開原msg然後創建一個從片,更換一個新的。我已經完成了用戶創建的用於創建文本塊佈局的簡短字符串,但StringBuilder對於更長的字符串和/或大量替換更快,效率更高。 This post is an extreme example使用1MB字符串(SB從5分鐘切到86毫秒)。

由於聽起來像你構建的起始字符串正在被切碎,如果可能的話,我會嘗試從頭開始構建它並沿着它的方式進行格式化。我不知道有足夠的瞭解數據或者一些其他的方法,但是這應該給你一個想法:

Public Class MessageMaker 
    Public Property Name As String 
    Public Property Target As String 
    Public Property Amount As Nullable(Of Decimal) 
    Public Property Cost As String   ' string? Really? 

    ' illustration 
    Public Property Participants As List(Of String) 
    ' ergo participantCount==Participants.COunt() 

    Public Property GroupName As String 
    ' etc ad nauseum 

    Public Sub New() 
     Participants = New List(Of String) 
    End Sub 

    Public Function GetFormattedMsg() As String 
     Dim sb As New StringBuilder 

     sb.AppendFormat("The Name: {0}; ", Name) 
     ' or...this will only append the name when lengh>0 
     'sb.AppendFormat(If(String.IsNullOrEmpty(Name), "", TitleCase(Name) & "; ")) 

     If Amount.HasValue Then 
      sb.AppendFormat("amt = {0}; ", Amount.Value.ToString("C2")) 
     End If 

     Dim p As String = "" 
     If Participants.Count > 0 Then 
      sb.AppendFormat("Participant Count: {0}; ", Participants.Count) 
      ' convert names to TitleCase, sort 
      p = String.Join(", ", Participants.OrderBy(Function(x) x). 
          Select(Function(j) TitleCase(j))) 

      sb.AppendFormat("Participant Names: {0}; ", p) 
     End If 

     sb.Append(If(String.IsNullOrEmpty(GroupName), "", 
            String.Format("Grp: {0}; ", TitleCase(GroupName)))) 

     Return sb.ToString 

    End Function 

    Private Function TitleCase(str As String) As String 
     Return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower) 
    End Function 

End Class 

注意,AmountNullable(Of Decimal)(或者可以寫成As Decimal?)。如果您想要省略它,則可以使用.HasValue來確定。這可以防止誤導性的數字:Amount: 0真的意味着0或它是否意味着它沒有指定。不要打擾Nullable<T>,除非這個問題。

GroupName處理顯示如何有條件地添加文本。我也將舊的StrConv替換爲NET方法。我不知道GetSortedGroups是幹什麼的,但是如果你想要的話,任何組列表都可以在飛行中排序(如Participants所示)。

根據還有什麼這個類需要做的,而不是方法,那結果可能來自.ToString()

Public Overrides Function ToString() As String 
    ' all the code 
    Return msg 
End Function 

測試代碼:

Dim mm As New MessageMaker 
mm.Name = "April Gala Festival" 
mm.Amount = 1.23D 
mm.Participants = New List(Of String) From {"ziggy", "zOEy", "HOOveR", "josh"} 

Dim msg = mm.GetFormattedMsg() 
' or 
Dim msg = mm.ToString() 

結果:

「名稱:四月聯歡晚會;獎金= 1.23美元;參加人數:4;參與者姓名:胡佛,喬希,齊吉,佐伊;」

我猜測結果字符串有一些標題和分隔符。該方法在每個片段或元素之後使用"; "

+0

我明白了。我想我知道我現在需要做什麼。一如既往的無條件幫助。謝謝。 – Josh