重构:如何使用未知类型进行重构?

时间:2010-03-02 08:29:06

标签: c# refactoring asp.net-2.0

我不知道如何使用“T”,我从来没有理解它,但我确信答案将存在于它周围的任何地方......

我有一个巨大的开关,它所做的就是将一个属性应用于一个对象并将控件添加到一个集合中,类型为Extract>应用属性>添加,如:

第一次切换

foreach (AdwizaControl control in form.AdwizaControls)
{
    Panel panel = new Panel();
    int x = 0, y = 0;
    switch (control.Type)
    {

        case ControlType.CheckBox:
            AdwizaCheckBox checkbox = (AdwizaCheckBox)control.AdwizaWebControl;
            x = checkbox.X;
            y = checkbox.Y;
            panel.Controls.Add(checkbox);
            break;
        case ControlType.Bevel:
            AdwizaBevel bevel = (AdwizaBevel)control.AdwizaWebControl;
            bevel.Width = bevel.W;
            bevel.Height = bevel.H;
            panel.Controls.Add(bevel);
            break;

checkbox.X和checkbox.Y是定义XML的属性,这里我们将控件设置为该大小

...

第二个开关(循环遍历RadPageView(Telerik组件)内的控件

foreach (RadPageView pageView in multiPage.PageViews)
{
    int controlCount = pageView.Controls.Count;

    for (int i = 0; i < controlCount; i++)
    {
        if (pageView.Controls[i].GetType() == typeof(AdwizaControl))
        {
            switch (((AdwizaControl)pageView.Controls[i]).Type)
            {

...

case ControlType.Grid:
    AdwizaGrid pageViewGrid = (AdwizaGrid)((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    pageViewGrid.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewGrid.Y + increaseY, pageViewGrid.X + increaseX));
    pageView.Controls.Add(pageViewGrid);
    break;
case ControlType.Hyperlink:
    AdwizaHyperlink pageViewHyperlink = (AdwizaHyperlink)((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    pageViewHyperlink.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewHyperlink.Y + increaseY, pageViewHyperlink.X + increaseX));
    pageView.Controls.Add(pageViewHyperlink);
    break;
case ControlType.ImageBox:
    AdwizaImageBox pageViewImageBox = (AdwizaImageBox)((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    pageViewImageBox.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewImageBox.Y + increaseY, pageViewImageBox.X + increaseX));
    pageView.Controls.Add(pageViewImageBox);
    break;
case ControlType.Label:
    AdwizaLabel pageViewlabel = (AdwizaLabel)((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    pageViewlabel.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewlabel.Y + increaseY, pageViewlabel.X + increaseX));
    pageView.Controls.Add(pageViewlabel);
    break;
case ControlType.Slavebox:
    AdwizaSlavebox pageViewSlavebox = (AdwizaSlavebox)((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    pageViewSlavebox.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewSlavebox.Y + increaseY, pageViewSlavebox.X + increaseX));

    pageView.Controls.Add(pageViewSlavebox);
    break;
case ControlType.Repeatbox:
    AdwizaRepeatBox pageViewrepeatbox = (AdwizaRepeatBox)((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    pageViewrepeatbox.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewrepeatbox.Y + increaseY, pageViewrepeatbox.X + increaseX));
    pageView.Controls.Add(pageViewrepeatbox);
    break;

它更大,因为它必须覆盖我正在使用的所有物体......

如何通过简单的通话来解决这个问题?有点像:

ApplyPositionAttribute(
    ((AdwizaControl)pageView.Controls[i]).AdwizaWebControl);

有没有办法简化这个?


切换语句

3 个答案:

答案 0 :(得分:0)

我了解所有类AdwizaGridAdwizaHyperlink等都有AdwizaControl作为公共基类。我还假设在基类中定义了Attributes。在这种情况下,您可以删除大部分重复内容,如下所示:

AdwizaControl control;

case ControlType.Grid:
    control = ((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    break;
case ControlType.Hyperlink:
    control = ((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
    break;
...

然后案件:

control.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;",
        control.Y + increaseY, control.X + increaseX));
pageView.Controls.Add(control);

在此之后,你可以用从控件类型到属性的某种映射替换大开关(我不熟悉C#所以我不能给你一个确切的提示,但是例如在C ++中你可以使用函子或者指向成员的指针)。

答案 1 :(得分:0)

如果AdwizaRepeatBox,AdwizaRepeatBox,AdwizaSlavebox和其他人没有扩展具有属性属性的单个类,那么您最好搜索反射命名空间以获得答案或重写您的代码以便他们扩展单个类

如果他们扩展单个类而不是您要查找的代码应该如下所示:

private void ApplyPositionAttribute<T>(AdwizaWebControl webControl) where T : InheritedClass
{
    /* ... */

    T adwizalControl = (T)webControl;
    pageViewrepeatbox.Attributes.Add(
        "style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewrepeatbox.Y + increaseY, pageViewrepeatbox.X + increaseX));
    pageView.Controls.Add(pageViewrepeatbox);
}

修改

如果所有adwizaControl扩展具有Attributes属性的单个类,请使用此选项。如果扩展X和Y属性,请使用virtual关键字覆盖基类声明

AdwizaWebControl webControl = ((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
webControl.Attributes.Add("style", string.Format("position:absolute;top:{0}px;left:{1}px;", webControl.Y + increaseY, webControl.X + increaseX));
pageView.Controls.Add(webControl);

答案 2 :(得分:0)

在这种情况下,您不必使用泛型。如果您的所有控件都继承自AdvizaWebControl,您可以这样写:

AdwizaWebControl webControl = ((AdwizaControl)pageView.Controls[i]).AdwizaWebControl;
webControl.Attributes.Add("style", string.Format("position:absolute;top:{0}px;left:{1}px;", pageViewGrid.Y + increaseY, pageViewGrid.X + increaseX));
pageView.Controls.Add(webControl);

但是,如果您的类不从AdwizaWebControl继承,那么泛型将无济于事。