Linq Expression Refactor重复代码

时间:2014-05-31 07:52:48

标签: c# asp.net-mvc linq func linq-expressions

我有一些相当重复的代码会导致一些令人头疼的问题。

表达式来; FUNC< TModel,DateTime>>

public static HelperResult DataPickerFor<TModel>(
   HtmlHelper<TModel> html, Expression<Func<TModel, DateTime>> func, // DateTime
   IControlData data = null, Object htmlAttributes = null)
{
    data = data ?? new ControlData();
    data.ControlId = func.GetName();
    var dict = AddValueBinding(func, data, htmlAttributes);
    var label = html.LabelFor(func);
    var scriptResult = DateChangeEvent(data);
    var changeEvent = data.ControlId + "ChangeEvent"; 
    var input = html.Kendo().DatePickerFor(func).Format(
           Constants.Format.Date)
        .Events(e => e.Change(changeEvent)).HtmlAttributes(dict)
        .ParseFormats(new[] { Constants.Format.Date });
    return FormFieldTemplate(label, input, "date", scriptResult);
}

表达式来; FUNC&LT;的TModel,日期时间&GT;?&GT;

public static HelperResult DataPickerFor<TModel>(
   HtmlHelper<TModel> html, Expression<Func<TModel, DateTime?>> func, // DateTime?
   IControlData data = null, Object htmlAttributes = null)
{
    data = data ?? new ControlData();
    data.ControlId = func.GetName();
    var dict = AddValueBinding(func, data, htmlAttributes);
    var label = html.LabelFor(func);
    var scriptResult = DateChangeEvent(data);
    var changeEvent = data.ControlId + "ChangeEvent"; 
    var input = html.Kendo().DatePickerFor(func)
        .Format(Constants.Format.Date)
        .Events(e => e.Change(changeEvent))
        .HtmlAttributes(dict).ParseFormats(new[] { Constants.Format.Date });
    return FormFieldTemplate(label, input, "date", scriptResult);
}

唯一真正的区别是DateTime?和日期时间。如果我使用a使代码通用  DatePickerFor将中断,因为它不能推断DateTime类型。

我可以投Func吗?

任何其他想法也会很棒!还有一些我没有添加的排列,所以只是生活在重复的代码中并不是一个想法。

DatePickerFor的签名:

public virtual DatePickerBuilder DatePickerFor(
    Expression<Func<TModel, DateTime?>> expression);
public virtual DatePickerBuilder DatePickerFor(
    Expression<Func<TModel, DateTime>> expression);

2 个答案:

答案 0 :(得分:3)

如果传递DatePickerFor函数的委托,则可以使函数通用。

public static HelperResult DataPickerFor<TModel, TDateTime>(
   HtmlHelper<TModel> html, Expression<Func<TModel, TDateTime>> func,
   Func<Expression<Func<TModel, TDateTime>>, HelperResult> f,
   IControlData data = null, Object htmlAttributes = null)
{
    data = data ?? new ControlData();
    data.ControlId = func.GetName();
    var dict = AddValueBinding(func, data, htmlAttributes);
    var label = html.LabelFor(func);
    var scriptResult = DateChangeEvent(data);
    var changeEvent = data.ControlId + "ChangeEvent"; 
    var input = f(func)
        .Format(Constants.Format.Date)
        .Events(e => e.Change(changeEvent))
        .HtmlAttributes(dict).ParseFormats(new[] { Constants.Format.Date });
    return FormFieldTemplate(label, input, "date", scriptResult);
}

然后你的重载成为

public static HelperResult DataPickerFor<TModel>(
   HtmlHelper<TModel> html, Expression<Func<TModel, DateTime>> func, // DateTime?
   IControlData data = null, Object htmlAttributes = null)
{
    return DataPickerFor<TModel, DateTime>(html, func, f => html.Kendo().DatePickerFor(f), data, htmlAttributes);
}

public static HelperResult DataPickerFor<TModel>(
   HtmlHelper<TModel> html, Expression<Func<TModel, DateTime?>> func, // DateTime?
   IControlData data = null, Object htmlAttributes = null)
{
    return DataPickerFor<TModel, DateTime?>(html, func, f => html.Kendo().DatePickerFor(f), data, htmlAttributes);
}

你可以这么简化:

public static HelperResult DataPickerFor<TModel, TDateTime>(
   HtmlHelper<TModel> html, Expression<Func<TModel, TDateTime>> func,
   HelperResult hr,
   IControlData data = null, Object htmlAttributes = null)
{
    data = data ?? new ControlData();
    data.ControlId = func.GetName();
    var dict = AddValueBinding(func, data, htmlAttributes);
    var label = html.LabelFor(func);
    var scriptResult = DateChangeEvent(data);
    var changeEvent = data.ControlId + "ChangeEvent"; 
    var input = hr
        .Format(Constants.Format.Date)
        .Events(e => e.Change(changeEvent))
        .HtmlAttributes(dict).ParseFormats(new[] { Constants.Format.Date });
    return FormFieldTemplate(label, input, "date", scriptResult);
}

public static HelperResult DataPickerFor<TModel>(
   HtmlHelper<TModel> html, Expression<Func<TModel, DateTime>> func, // DateTime?
   IControlData data = null, Object htmlAttributes = null)
{
    return DataPickerFor<TModel, DateTime>(html, func, html.Kendo().DatePickerFor(func), data, htmlAttributes);
}

public static HelperResult DataPickerFor<TModel>(
   HtmlHelper<TModel> html, Expression<Func<TModel, DateTime?>> func, // DateTime?
   IControlData data = null, Object htmlAttributes = null)
{
    return DataPickerFor<TModel, DateTime?>(html, func, html.Kendo().DatePickerFor(func), data, htmlAttributes);
}

答案 1 :(得分:0)

你可以转换表达式&lt; FUNC&LT; TModel,DateTime&gt;&gt;表达&lt; FUNC&LT; TModel,DateTime?&gt;&gt;,这样就可以消除代码重复。转换是在我的ConvertExpression方法中实现的。

当然,我们并不完全了解您的问题的背景,但也许您会发现此解决方案很有趣 - 尽管此解决方案的效果不如接受的解决方案。

    private void RunTest()
    {
        Expression<Func<string, DateTime?>> exp1 = p => new DateTime(2001, 1, 1);
        TestExpression(exp1, "exp1");

        Expression<Func<string, DateTime>> exp2 = p => new DateTime(2002, 2, 2);
        TestExpression(ConvertExpression(exp2), "exp2");
    }

    private void TestExpression<T>(Expression<Func<T, DateTime?>> expression, T parameter)
    {
        DateTime? dateTime = expression.Compile().Invoke(parameter);

        Console.WriteLine("DateTime to {0} is {1}", parameter, dateTime);
    }

    private Expression<Func<T, DateTime?>> ConvertExpression<T>(Expression<Func<T, DateTime>> expression)
    {
        var func = expression.Compile();
        Expression<Func<T, DateTime?>> convertedExpression = p => func(p);

        return convertedExpression;
    }

输出:

exp1的DateTime是2001.01.01。 0点00分00秒

到exp2的DateTime是2002.02.02。 0点00分00秒