2010-09-09 1 views
6

За несколько лет я сделал ASP.NET веб-форм развития я был испорчен собственной библиотеки, что позволило мне делать такие вещи, как:Model Binder в ASP.NET WebForms

UpdateToObject(ControlsCollection, obj) 
    UpdateFromObject(ControlsCollection, obj) 

Концептуально код сделал что-то очень аналогично тому, что делает MVC Model Binder, т. е. заданные формы в качестве входных данных будут заполнять пользовательский объект. В основном это освободило разработчик делать обезьяны код, такой как

employee.Name = txtName.Text; 
employee.DOB = DateTime.Parse(txtDOB.Text); 

и так далее ..

Теперь эта фирменная библиотека не доступна на новом проекте я участвую с, и это проект веб-формы , Поэтому мне интересно, есть ли способ использования System.Web.Mvc.DefaultModelBinder в контексте веб-форм. Цель состоит в том, чтобы достичь простой и простой совокупности элементов управления от объектов домена и обратно, в идеале с учетом аннотаций проверки. Если это невозможно, кто-то может указать мне на решение с открытым исходным кодом для решения этой проблемы. Мне действительно не хочется переписывать такой код.

Заранее спасибо.

ответ

1

Шерлок, вы столкнетесь с некоторыми проблемами, пытающимися использовать 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); 
    } 
    } 

Извините, независимо от того, что я делаю редактор полностью путает код листинга. Но я надеюсь, что это поможет.

+0

Только один и последний абзацы имеют отношение к поднятому вопросу. Я не против использования рефлексии. Так работала собственная библиотека. – Sherlock

+0

Я думаю, в вашем случае, потому что вы работаете с Controls, решение немного более активно. Класс DtoBinder может создать экземпляр вашего объекта Dto и присвоить все значения свойств, учитывая коллекцию NameValues. Итак, что вам нужно сделать, это собрать эту коллекцию из имен и значений элемента управления и передать ее в DtoBinder. –

+0

Просто отредактировал мой оригинальный ответ с некоторыми дополнительными классами, которые я использовал в прошлом. –

1

Не могли бы вы использовать AutoMapper для чего-то подобного? Просто настройте свои карты и создайте новые объекты и скопируйте их в них.

0

Это довольно старый вопрос, но я натолкнулся на него, пытаясь понять, как на самом деле работает связующее устройство по умолчанию.

У меня есть проект CodeProject, который фактически делает то, что вы хотите (ed), have a look.

Cheers!

 Смежные вопросы

  • Нет связанных вопросов^_^