[英]How can I pass a property of a class as a parameter of a method?
我有一個類,有十幾個屬性代表各種金融領域。 我有另一個類需要分別對每個字段執行一些計算。 這些計算方法中的代碼是相同的,除了它進行計算的字段。
有沒有辦法可以將屬性名稱作為參數傳遞,只有一個方法可以執行所有執行工作而不是每個屬性的12個方法?
此外,我確信這可以通過反射來完成,但我已經在其他代碼中看到lambda以同樣的方式使用,並且想知道這是否是可以使用它的候選者。
根據要求,這是一個例子:
public class FinancialInfo
{
public virtual DateTime AuditDate { get; set; }
public virtual decimal ReleasedFederalAmount { get; set; }
public virtual decimal ReleasedNonFederalAmount { get; set; }
public virtual decimal ReleasedStateAmount { get; set; }
public virtual decimal ReleasedLocalAmount { get; set; }
public virtual decimal ReleasedPrivateAmount { get; set; }
// more fields like this
}
public class FinancialLedger()
{
public virtual DateTime? BeginDate { get; set; }
public virtual DateTime? EndDate { get; set; }
public virtual IList<FinancialInfo> Financials { get; set; } //not actual implementation, but you get the idea
public decimal GetTotalReleasedFederalAmountByDate()
{
if (BeginDate == null && EndDate == null)
return 0;
decimal total = 0;
foreach (var fi in Financials)
{
if (someCondition)
if (someSubCondition)
total += fi.ReleasedFederalAmount;
else if (someOtherCondition)
if (someOtherSubCondition)
total += fi.ReleasedFederalAmount;
else if (anotherCondigion)
total += fi.ReleasedFederalAmount;
}
return total;
}
public decimal GetTotalReleasedNonFederalAmountByDate()
{
// same logic as above method,
// but it accesses fi.ReleasedNonFederalAmount;
}
// More methods the same as the previous, just accessing different
// members of FinancialInfo
}
我的目標是只創建一個名為GetTotalAmountByDate()的方法,並傳入一個開始日期,結束日期以及它需要訪問的屬性名稱(ReleasedFederalAmount或ReleasedLocalAmount等)。
我希望這能准確地描繪出我想要實現的目標。
如果您的屬性都是數字並且可以被均勻地視為單一類型,則不需要反射 - 讓我們說decimal
。
像這樣的東西應該做的伎倆:
protected decimal ComputeFinancialSum( DateTime? beginDate, DateTime? endDate,
Func<FinancialInfo,decimal> propertyToSum )
{
if (beginDate == null && endDate == null)
return 0;
decimal total = 0;
foreach (var fi in Financials)
{
if (someCondition)
if (someSubCondition)
total += propertyToSum(fi);
else if (someOtherCondition)
if (someOtherSubCondition)
total += propertyToSum(fi);
else if (anotherCondigion)
total += propertyToSum(fi);
}
return total;
}
然后,您可以為所有特定情況提供適當命名的版本:
public decimal GetTotalReleasedFederalAmountByDate()
{
return ComputeFinancialSum( BeginDate, EndDate,
(x) => x.ReleasedFederalAmount );
}
public decimal GetTotalReleasedNonFederalAmountByDate()
{
return ComputeFinancialSum( BeginDate, EndDate,
(x) => x.ReleasedNonFederalAmount );
}
// other versions ....
除了Jon Skeet基於lamba的好建議,你可以嘗試這樣的事情。 (當然,它可能會改變你的一些代碼的工作方式。)
public class ValueHolder
{
object Value;
}
public class Main
{
private ValueHolder value1 = new ValueHolder();
private ValueHolder value2 = new ValueHolder();
public Value1 { get { return value1.Value; } set { value1.Value = value; } }
public Value2 { get { return value2.Value; } set { value2.Value = value; } }
public ValueHolder CalculateOne(ValueHolder holder ...)
{
// Whatever you need to calculate.
}
public CalculateBoth()
{
var answer1 = CalculateOne(value1);
var answer2 = CalculateOne(value2);
...
}
}
這可能是這里最低技術的答案,但為什么不只是使用一個開關並合並多個“GetTotal ... Amount”函數?
// define some enum for your callers to use
public enum AmountTypeEnum {
ReleasedFederal = 1
, ReleasedLocal = 2
}
public decimal GetTotalAmountByDate(AmountTypeEnum type)
{
if (BeginDate == null && EndDate == null)
return 0;
decimal total = 0;
foreach (var fi in Financials)
{
// declare a variable that will hold the amount:
decimal amount = 0;
// here's the switch:
switch(type) {
case AmountTypeEnum.ReleasedFederal:
amount = fi.ReleasedFederalAmount; break;
case AmountTypeEnum.ReleasedLocal:
amount = fi.ReleasedLocalAmount; break;
default: break;
}
// continue with your processing:
if (someCondition)
if (someSubCondition)
total += amount;
else if (someOtherCondition)
if (someOtherSubCondition)
total += amount;
else if (anotherCondigion)
total += amount;
}
return total;
}
這似乎更安全,因為你的所有邏輯都在你的控制之下(沒有人通過你的功能來執行)。
如果你需要用不同的金額實際做不同的事情,這可以進一步細分:
獲取處理部分並將其轉換為函數:
private decimal ProcessNormal(decimal amount) {
decimal total = 0;
// continue with your processing:
if (someCondition)
if (someSubCondition)
total += amount;
else if (someOtherCondition)
if (someOtherSubCondition)
total += amount;
else if (anotherCondition)
total += amount;
return total;
}
public decimal GetTotalAmountByDate(AmountTypeEnum type)
{
if (BeginDate == null && EndDate == null)
return 0;
decimal total = 0;
foreach (var fi in Financials)
{
// declare a variable that will hold the amount:
decimal amount = 0;
// here's the switch:
switch(type) {
case AmountTypeEnum.ReleasedFederal:
amount = fi.ReleasedFederalAmount;
total = ProcessNormal(amount);
break;
case AmountTypeEnum.ReleasedLocal:
amount = fi.ReleasedLocalAmount;
total = ProcessNormal(amount);
break;
case AmountTypeEnum.NonReleasedOtherAmount:
amount = fi.NonReleasedOtherAmount;
total = ProcessSlightlyDifferently(amount); // for argument's sake
break;
default: break;
}
}
return total;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.