3
\$\begingroup\$

After several attempts to follow my intuition that this code can be refactored to something more DRY, I keep hitting road blocks.

Hoping someone can see a refactor that might get me going in a nicer direction.

I'm trying not to break anything out of this one code file, although, I suppose helper types could be placed in a top level code block if they help.

This razor view essentially presents all string string types in an arbitrarily complex type as a single form:

Member.cshtml

@model Tuple<object, Type, string>
@{
    var targetObj = Model.Item1;
    var targetType = Model.Item2;
    var path = Model.Item3;
}
<ul class="list-group" style="list-style-type: none">
    @foreach (var prop in
        from p in targetType.GetProperties()
        where p.Name != "SyncRoot"
        orderby p.Name
        select p)
    {
        var name = (path + "." + prop.Name).TrimStart('.');
        if (prop.PropertyType == typeof (string))
        {                    
            var value = "";
            if (targetObj != null)
            {
                var propValue = prop.GetValue(targetObj);
                if (propValue != null)
                {
                    value = propValue.ToString();
                }
            }
            <li class="list-group-item">
                <label>@prop.Name</label>
                <input class="form-control" value="@value" name="@name"/>
            </li>
        }
        else if (prop.PropertyType.IsArray && prop.PropertyType.GetElementType() == typeof (string))
        {
            var value = "";
            if (targetObj != null)
            {
                var propValue = prop.GetValue(targetObj) as string[];
                if (propValue != null)
                {
                    value = propValue[0];
                }
            }
            <li class="list-group-item">
                <label class="control-label col-md-2">@(prop.Name)[]</label>
                <input class="form-control" value="@value" name="@(name)[0]"/>
            </li>
        }
        else if (prop.PropertyType.IsArray)
        {
            object value = null;
            if (targetObj != null)
            {
                value = prop.GetValue(targetObj);
            }
            <li class="list-group-item">
                <fieldset>
                    <legend>@(prop.Name)[]</legend>
                    @Html.Partial("Member", Tuple.Create(value, prop.PropertyType.GetElementType(), name))
                </fieldset>
            </li>
        }
        else if (!prop.PropertyType.Name.StartsWith("System."))
        {
            object value = null;
            if (targetObj != null)
            {
                value = prop.GetValue(targetObj);
            }
            <li class="list-group-item">
                <fieldset>
                    <legend>@prop.Name</legend>
                    @Html.Partial("Member", Tuple.Create(value, prop.PropertyType, name))
                </fieldset>
            </li>
        }
    }
</ul>
\$\endgroup\$
3
\$\begingroup\$

Having a chain of if...elseif s it is a good place to start having a registry/resolver container instead.

Please take a look at my answer here.

After refactoring the code and removing the nested if....else s you will have all the logic and actions in one place to look at and you can refactor them in order to be DRY.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.