intリストをパラメーターとしてWebユーザーコントロールに渡す
-
05-07-2019 - |
質問
int型リスト(リスト)を宣言的なプロパティとして、次のようなWebユーザーコントロールに渡したい:
<UC:MyControl runat="server" ModuleIds="1,2,3" />
これを行うためにTypeConverterを作成しました:
public class IntListConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(
System.ComponentModel.ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string)) return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(
System.ComponentModel.ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
string[] v = ((string)value).Split(
new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
List<int> list = new List<int>();
foreach (string s in vals)
{
list.Add(Convert.ToInt32(s));
}
return list
}
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext context,
Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor)) return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor) && value is List<int>)
{
List<int> list = (List<int>)value;
ConstructorInfo construcor = typeof(List<int>).GetConstructor(new Type[] { typeof(IEnumerable<int>) });
InstanceDescriptor id = new InstanceDescriptor(construcor, new object[] { list.ToArray() });
return id;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
そして、プロパティに属性を追加しました:
[TypeConverter(typeof(IntListConverter))]
public List<int> ModuleIds
{
get { ... }; set { ... };
}
しかし、実行時にこのエラーが表示されます:
Unable to generate code for a value of type 'System.Collections.Generic.List'1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'. This error occurred while trying to generate the property value for ModuleIds.
私の質問はこちら、しかし、解決策は私の問題を解決しません:
更新:最初の問題を解決したページを見つけました。上記のコードを更新して、修正内容を示しました。追加されたコードは、CanConvertTo
およびConvertTo
メソッドです。今、私は別のエラーを受け取ります。:
Object reference not set to an instance of an object.
このエラーは<=>メソッドの何かによって間接的に引き起こされているようです。
解決
デバッガをCassiniにフックすると、null refが実際にSystem.Web.Compilation.CodeDomUtility.GenerateExpressionForValueから来ていることがわかります。これは、基本的にListコンストラクターに渡すint []配列の式を取得しようとしています。 。 int []配列には型記述子がないため失敗します(プロセス内で<!> quot;プロパティセット例外<!> quotを生成できない代わりにnull refをスローします)
シリアル化可能な値をList <!> lt; int <!> gt;に取り込む方法がわからないため、静的メソッドを使用しました:
class IntListConverter : TypeConverter {
public static List<int> FromString(string value) {
return new List<int>(
value
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => Convert.ToInt32(s))
);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
if (destinationType == typeof(InstanceDescriptor)) {
List<int> list = (List<int>)value;
return new InstanceDescriptor(this.GetType().GetMethod("FromString"),
new object[] { string.Join(",", list.Select(i => i.ToString()).ToArray()) }
);
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
他のヒント
このエラーに関して特定の経験があるとは言えませんが、他のソースは、タイプInstanceDescriptorに変換を追加する必要があることを示しています。チェックアウト:
http://weblogs.asp.net/bleroy /archive/2005/04/28/405013.aspx
理由の説明を提供するか、代わりに:
http://forums.asp.net/p/1191839/2052438 .aspx#2052438
あなたに似たサンプルコードを提供します。
2つのプロパティを作成して、似たような問題を解決しました:
public List<int> ModuleIDs { get .... set ... }
public string ModuleIDstring { get ... set ... }
ModuleIDstringは、値セットをリストに変換し、ModuleIDsプロパティを設定します。
これにより、PropertyGridなどからModuleIDが使用可能になります。
わかりました、最良のタイプセーフなソリューションではありませんが、私にとってはうまくいきます。
コードビハインドからリストを渡す...
aspx:
<UC:MyControl id="uc" runat="server" />
コードビハインド:
List<int> list = new List<int>();
list.add(1);
list.add(2);
list.add(3);
uc.ModuleIds = list;
通常これを行う方法は、プロパティがViewStateコレクションをラップするようにすることです。動作させることができれば、あなたの方法はより良く見えますが、これで仕事が完了します:
public IList<int> ModuleIds
{
get
{
string moduleIds = Convert.ToString(ViewState["ModuleIds"])
IList<int> list = new Collection<int>();
foreach(string moduleId in moduleIds.split(","))
{
list.Add(Convert.ToInt32(moduleId));
}
return list;
}
}
問題はセット{}だと思います。タイプコンバーターはList<int>
を文字列に戻したいが、CanConvertFrom()
が<=>に対して失敗する。
それを文字列に渡し、コンマで分割してプライベート変数を設定できます。帰属表示の機能はありませんが、機能します。
private List<int> modules;
public string ModuleIds
{
set{
if (!string.IsNullOrEmpty(value))
{
if (modules == null) modules = new List<int>();
var ids = value.Split(new []{','});
if (ids.Length>0)
foreach (var id in ids)
modules.Add((int.Parse(id)));
}
}
最善の選択肢は、ユーザーコントロールにDataSourceスタイルのプロパティを持たせることだと思います。
プロパティをオブジェクトとして取得し、IList / IEnumerable /などに対して型チェックを行い、正しいことを確認します。