Шерлок, вы столкнетесь с некоторыми проблемами, пытающимися использовать ModelBinder из MVC, поскольку они полагаются на ControllerContext.
Я ответил на подобный вопрос ранее ChangeType, Convert - Converting from one type to another, но это действительно то, что вы ищете.
Заканчивать этот пост в блоге на своем блоге ChangeType – Changing the type of a variable in C#
По сути, вы получаете один метод, называемый ChangeType<T>
, который возвращает значение параметра, который вы ищете в сильно типизированных моде или значение по умолчанию, если параметр не существует.
Что касается пользовательских классов (в основном классов классов DTO), если вы не против использования отражения, то у меня есть решение, которое будет обрабатывать большинство пользовательских классов. Класс DtoBinder, упомянутый в конце работы, будет приятным.
По сути, последние 3 списка кода содержат весь код, который вам нужен, чтобы обрабатывать практически все ваши потребности в типичном сценарии веб-приложений. Кроме того, он расширяемый, поэтому, если вам нужно реализовать собственное связующее, вы можете сделать это очень просто и зарегистрировать свое связующее с RequestBinder из любого места в вашем приложении.
Поэтому, если вы не хотите использовать отражение для некоторых часто используемых объектов DTO, вы можете реализовать связующее для типа и зарегистрировать его, и с этой точки на нем будет использоваться ваше настраиваемое связующее. Во многом это похоже на концепт MVC ModelBinder.
Edited -
Ниже это один .cs файл с кучей классов, которые я использовал в прошлом, чтобы сделать именно то, что вам нужно. Первый MsPropertyAssignerProvider - это тот, с которым вы будете работать с вашей страницы.
Вы должны перебирать элементы управления и вызывать метод GetPropertyAssigner, передавая ему имя типа элемента управления. Этот метод возвращает экземпляр объекта ObjectPropertyAssigner, у которого есть один метод SetPropertyValue, который вы можете передать экземпляру объекта и экземпляру элемента управления.
internal class MsPropertyAssignerProvider
{
private Hashtable propertyAssigners;
internal MsPropertyAssignerProvider()
{
propertyAssigners = new Hashtable();
RegisterPropertyAssigner(typeof(TextBox).ToString(), new TextBoxValueExtractor());
RegisterPropertyAssigner(typeof(DropDownList).ToString(), new DropDownListValueExtractor());
RegisterPropertyAssigner(typeof(Label).ToString(), new LabelValueExtractor());
RegisterPropertyAssigner(typeof(CheckBox).ToString(), new CheckBoxValueExtractor());
}
internal void RegisterPropertyAssigner(string identifier, IMsObjectPropertyAssigner assigner)
{
if (propertyAssigners.ContainsKey(identifier))
throw new DuplicatePropertyAssignerRegistrationException(identifier);
propertyAssigners.Add(identifier, assigner);
}
internal IMsObjectPropertyAssigner GetPropertyAssigner(string identifier)
{
return (propertyAssigners.ContainsKey(identifier)) ? (IMsObjectPropertyAssigner)propertyAssigners[identifier] : null;
}
}
Сопроводительный класс не перечислены ниже
public interface IMsObjectPropertyAssigner
{
void SetPropertyValue(object obj, System.Web.UI.Control control);
}
internal abstract class BaseValueExtractor : IMsObjectPropertyAssigner
{
protected MsReflectionHelper reflectionHelper = new MsReflectionHelper();
protected string FixStringForNumber(string stringValue)
{
if (stringValue.Length == 0)
return "0";
else
return stringValue;
}
public abstract void SetPropertyValue(object obj, System.Web.UI.Control control);
}
internal class TextBoxValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, System.Web.UI.Control control)
{
TextBox textBox = (TextBox)control;
PropertyInfo propInfo = reflectionHelper.GetPropertyInfo(obj, control.ID);
Type propType = propInfo.PropertyType;
if (propType == typeof(System.String))
reflectionHelper.SetPropertyValue(obj, control.ID, textBox.Text);
else if (propType == typeof(System.Int16))
reflectionHelper.SetPropertyValue(obj, control.ID, Int16.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Int32))
reflectionHelper.SetPropertyValue(obj, control.ID, Int32.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Int64))
reflectionHelper.SetPropertyValue(obj, control.ID, Int64.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Double))
reflectionHelper.SetPropertyValue(obj, control.ID, Double.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else if (propType == typeof(System.Single))
reflectionHelper.SetPropertyValue(obj, control.ID, Single.Parse(FixStringForNumber(textBox.Text), System.Globalization.NumberStyles.Currency));
else
reflectionHelper.SetPropertyValue(obj, control.ID, textBox.Text);
}
}
internal class DropDownListValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, System.Web.UI.Control control)
{
DropDownList dropDownList = (DropDownList)control;
reflectionHelper.SetPropertyValue(obj, control.ID, dropDownList.SelectedValue);
}
}
internal class LabelValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, Control control)
{
Label label = (Label)control;
reflectionHelper.SetPropertyValue(obj, control.ID, label.Text);
}
}
internal class CheckBoxValueExtractor : BaseValueExtractor
{
public override void SetPropertyValue(object obj, Control control)
{
CheckBox checkbox = (CheckBox)control;
reflectionHelper.SetPropertyValue(obj, control.ID, checkbox.Checked);
}
}
Извините, независимо от того, что я делаю редактор полностью путает код листинга. Но я надеюсь, что это поможет.
Только один и последний абзацы имеют отношение к поднятому вопросу. Я не против использования рефлексии. Так работала собственная библиотека. – Sherlock
Я думаю, в вашем случае, потому что вы работаете с Controls, решение немного более активно. Класс DtoBinder может создать экземпляр вашего объекта Dto и присвоить все значения свойств, учитывая коллекцию NameValues. Итак, что вам нужно сделать, это собрать эту коллекцию из имен и значений элемента управления и передать ее в DtoBinder. –
Просто отредактировал мой оригинальный ответ с некоторыми дополнительными классами, которые я использовал в прошлом. –