Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing ifs based on type and list of parameters

I want to refactor following recursive method:

public static void Initialize(Control control, DocumentContainer container, ErrorProvider provider)
{
    if (control == null)
    {
        return;
    }

    var controlWithTextBase = control as ICustomControlWithText;
    if (controlWithTextBase != null)
    {
       controlWithTextBase.DocumentLoaded = true;
       controlWithTextBase.Initialize(container, provider);
    }

    var custom = control as CustomCheckbox;
    if (custom != null)
    {
        custom.DocumentLoaded = true;
        custom.Initialize(container);
    }

    foreach (Control subControl in control.Controls)
    {
        Initialize(subControl, container, provider);
    }
}


public interface ICustomControlWithText : ICustomControl
{
    void Initialize(DocumentContainer container, ErrorProvider provider);
    void InitializeValidations();

    string Text { get; set; }
    ErrorProvider ErrorProvider { get; set; }
    List<IValidation> Validations { get; set; }
}


public interface ICustomControl
{
    void Clear();

    FieldType FieldType { get; set; }
    bool DocumentLoaded { get; set; }
}

class CustomCheckbox : CheckBox, ICustomControl
{
     public void Initialize(DocumentContainer container)
    {
    //...
    }
}

As you can see, depends on type of winforms control this code initialize a control. It starts with main form, and this contains custom controls(IControlWithText,CustomCheckbox) and default winforms forms. I would create 3 Initializators and to every a method CanInitialize depending on type of a control, but even then I have no idea how can I skip those "ifs", which I need to know if I need send this ErrorProvider to method Initialize.

I would be very grateful for your help!

like image 311
user278618 Avatar asked May 29 '15 09:05

user278618


1 Answers

You can use "Dynamic Overload Resolution". (Requires .Net 4+)

If you cast your input control to dynamic, .Net will look for a suitable overload at runtime.
Be careful to provide a "catch" overload for the case of an unexpected type of control. This is what the object overload here is good for. Otherwise you might encounter runtime exceptions.

public static void Initialize(Control control, DocumentContainer container, ErrorProvider provider)
{
    if (control == null) return;

    dynamic c = control;       
    InitializeControl(c, container, provider);

    foreach (Control subControl in control.Controls)
        Initialize(subControl, container, provider);
}


public static void InitializeControl(ICustomControlWithText controlWithTextBase, DocumentContainer container, ErrorProvider provider)
{
    controlWithTextBase.DocumentLoaded = true;
    controlWithTextBase.Initialize(container, provider);
}

public static void InitializeControl(CustomCheckbox custom, DocumentContainer container, ErrorProvider provider)
{
    custom.DocumentLoaded = true;
    custom.Initialize(container);
}

public static void InitializeControl(object _, DocumentContainer container, ErrorProvider provider)
{
    // do nothing if the control is neither a ICustomControlWithText nor a CustomCheckbox
}
like image 151
3dGrabber Avatar answered Nov 07 '22 07:11

3dGrabber