Sherlock さん、MVC から ModelBinder を使用しようとすると、ControllerContext に依存しているため、いくつかの問題に遭遇するでしょう。
私は以前に同様の質問に答えましたChangeType, Convert - Converting from one type to anotherが、それは本当にあなたが探しているものです。
私のブログChangeTypeのこのブログ投稿をチェックしてください
– C# での変数の型の変更
ChangeType<T>
基本的に、厳密に型指定された方法で探しているパラメーターの値を返すか、パラメーターが存在しない場合は既定値を返す単一のメソッドが呼び出されます。
カスタム クラス (主に DTO 型クラス) に関しては、リフレクションの使用を気にしない場合は、ほとんどのカスタム クラスも処理できるソリューションがあります。最後の方で述べた DtoBinder クラスはうまく機能します。
基本的に、最後の 3 つのコード リストには、典型的な Web アプリケーション シナリオでのほとんどすべてのニーズに対応するために必要なすべてのコードが含まれています。さらに、拡張可能であるため、独自のバインダーを実装する必要がある場合は、非常に簡単に実装でき、アプリのどこからでもバインダーを RequestBinder に登録できます。
したがって、頻繁に使用される特定の DTO オブジェクトに対してリフレクションを使用したくない場合は、その型のバインダーを実装して登録すると、その時点からカスタム バインダーが使用されます。多くの点で、概念は MVC ModelBinder に似ています。
編集済み -
以下は、必要なことを正確に行うために過去に使用した一連のクラスを含む .cs ファイルの 1 つです。最初の MsPropertyAssignerProvider は、ページ内から操作するものです。
コントロールを繰り返し処理し、コントロールの型名を渡して GetPropertyAssigner メソッドを呼び出します。このメソッドは、オブジェクト インスタンスとコントロール インスタンスを渡すことができる SetPropertyValue という 1 つのメソッドを持つ ObjectPropertyAssigner のインスタンスを返します。
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);
}
}
申し訳ありませんが、私が何をしても、エディターはコード リストを完全に台無しにします。しかし、これが役立つことを願っています。