将属性传递给方法时实现更清晰

发布于 2024-09-19 19:21:15 字数 2341 浏览 4 评论 0原文

我正在为我正在开发的系统编写一个 csv 导入引擎,我想避免使用看起来像这样的代码(重复 10 列):

var field = GetFieldStringValue(columnCode);
if (IsValidDecimal(field))
{
    currentRow.Amount = Decimal.Parse(field);
}
else
{
    ReportError();
}

最后我选择了一个看起来像这样的方法(带有重载)对于各种类型):

    private void SetPropertyOrReportError(Action<decimal?> e, string columnCode)
    {
        if (IsValidDecimal(columnCode))
        {
            var fieldValue = Decimal.Parse(GetFieldStringValue(columnCode));
            e(fieldValue);
        }
        else if (!IsColumRequired(columnCode))
        {
            e(null);
        }
        else
        {
            SetPropertyOrReportError();
        }
    }

这样,对于每一行,我最终得到的代码有点像这样:

var currentRow = new ClaimImportHelper();
SetPropertyOrReportError((e) => currentRow.ClaimantName = e, ClaimantNameColumnCode);
SetPropertyOrReportError((e) => currentRow.CustomerName = e, CustomerNameColumnCode);
SetPropertyOrReportError((e) => currentRow.CustomerProject = e, CustomerProjectColumnCode);
SetPropertyOrReportError((e) => currentRow.ClaimDate = e.Value, ClaimDateColumnCode);
SetPropertyOrReportError((e) => currentRow.ClaimSubmitted = e, ClaimSubmittedColumnCode);
SetPropertyOrReportError((e) => currentRow.ExpenseCategory = e, ExpenseCategoryColumnCode);
SetPropertyOrReportError((e) => currentRow.ExpenseType = e, ExpenseTypeColumnCode);
SetPropertyOrReportError((e) => currentRow.Amount = e.Value, AmountColumnCode);
SetPropertyOrReportError((e) => currentRow.PayeeReference = e, PayeeReferenceColumnCode);
SetPropertyOrReportError((e) => currentRow.Detail = e, DetailColumnCode);
SetPropertyOrReportError((e) => currentRow.TransactionDate = e, TransactionDateColumnCode);
parsedItems.Add(currentRow);

我认为更好,因为它更好地表达了其意图。然而,它仍然不是我想要的那样,我宁愿能够像这样调用该方法:

SetPropertyOrReportError(currentRow.ClaimantName, ClaimantNameColumnCode);
SetPropertyOrReportError(currentRow.CustomerName, CustomerNameColumnCode);
SetPropertyOrReportError(currentRow.CustomerProject, CustomerProjectColumnCode);
SetPropertyOrReportError(currentRow.ClaimDate, ClaimDateColumnCode);
SetPropertyOrReportError(currentRow.ClaimSubmitted, ClaimSubmittedColumnCode);

我遇到的问题是我无法理解如何编写一个表达式取得财产。我该怎么做?

I am writing an csv import engine for a system I'm working on and I wanted to avoid the kind of code that looks like (repeated for 10's of columns):

var field = GetFieldStringValue(columnCode);
if (IsValidDecimal(field))
{
    currentRow.Amount = Decimal.Parse(field);
}
else
{
    ReportError();
}

In the end I opted for a method that looks like this (with overloads for various types):

    private void SetPropertyOrReportError(Action<decimal?> e, string columnCode)
    {
        if (IsValidDecimal(columnCode))
        {
            var fieldValue = Decimal.Parse(GetFieldStringValue(columnCode));
            e(fieldValue);
        }
        else if (!IsColumRequired(columnCode))
        {
            e(null);
        }
        else
        {
            SetPropertyOrReportError();
        }
    }

That way for each row I end up with code a bit like this:

var currentRow = new ClaimImportHelper();
SetPropertyOrReportError((e) => currentRow.ClaimantName = e, ClaimantNameColumnCode);
SetPropertyOrReportError((e) => currentRow.CustomerName = e, CustomerNameColumnCode);
SetPropertyOrReportError((e) => currentRow.CustomerProject = e, CustomerProjectColumnCode);
SetPropertyOrReportError((e) => currentRow.ClaimDate = e.Value, ClaimDateColumnCode);
SetPropertyOrReportError((e) => currentRow.ClaimSubmitted = e, ClaimSubmittedColumnCode);
SetPropertyOrReportError((e) => currentRow.ExpenseCategory = e, ExpenseCategoryColumnCode);
SetPropertyOrReportError((e) => currentRow.ExpenseType = e, ExpenseTypeColumnCode);
SetPropertyOrReportError((e) => currentRow.Amount = e.Value, AmountColumnCode);
SetPropertyOrReportError((e) => currentRow.PayeeReference = e, PayeeReferenceColumnCode);
SetPropertyOrReportError((e) => currentRow.Detail = e, DetailColumnCode);
SetPropertyOrReportError((e) => currentRow.TransactionDate = e, TransactionDateColumnCode);
parsedItems.Add(currentRow);

Which I think is better since it expresses its intent better. However, it's still not as I'd like it to be, I'd rather be able to call the method like this:

SetPropertyOrReportError(currentRow.ClaimantName, ClaimantNameColumnCode);
SetPropertyOrReportError(currentRow.CustomerName, CustomerNameColumnCode);
SetPropertyOrReportError(currentRow.CustomerProject, CustomerProjectColumnCode);
SetPropertyOrReportError(currentRow.ClaimDate, ClaimDateColumnCode);
SetPropertyOrReportError(currentRow.ClaimSubmitted, ClaimSubmittedColumnCode);

The problem I'm having is that I can't get my head around how to write an Expression that will take a property. How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

十秒萌定你 2024-09-26 19:21:15

基本上你不能。

表达式 currentRow.ClaimantName 用作方法参数时,将始终表示对属性的 getter 求值的结果。

如果我们得到 infoof 运算符,可能有更好的方法 - 但目前,我认为您的 lambda 选项是最好的方法。请注意,您不需要参数周围的括号 - 例如:

SetPropertyOrReportError(e => currentRow.Detail = e, DetailColumnCode);

You can't, basically.

The expression currentRow.ClaimantName, when used as a method argument, will always represent the result of evaluating the getter for the property.

If we ever get the infoof operator, there might be a better approach - but for the moment, I think your lambda option is the best one. Note that you don't need the parentheses around the parameter though - for example:

SetPropertyOrReportError(e => currentRow.Detail = e, DetailColumnCode);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文