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>