Передача массива int в качестве параметра в веб-пользовательском управлении
У меня есть массив int как свойство Web User Control. Я хотел бы установить это свойство inline, если возможно, используя следующий синтаксис:
<uc1:mycontrol runat="server" myintarray="1,2,3" />
Это приведет к сбою во время выполнения, потому что ожидается ожидание массива int, но вместо этого передается строка. Я могу сделать строку myintarray
и проанализировать ее в установщике, но мне было интересно, было ли более элегантное решение.
Ответы
Ответ 1
Внедрите конвертер типов, вот один, предупреждающий: быстрый и грязный, а не для использования в производстве и т.д.:
public class IntArrayConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string val = value as string;
string[] vals = val.Split(',');
System.Collections.Generic.List<int> ints = new System.Collections.Generic.List<int>();
foreach (string s in vals)
ints.Add(Convert.ToInt32(s));
return ints.ToArray();
}
}
и пометьте свойство вашего элемента управления:
private int[] ints;
[TypeConverter(typeof(IntsConverter))]
public int[] Ints
{
get { return this.ints; }
set { this.ints = value; }
}
Ответ 2
@mathieu, большое спасибо за ваш код. Я несколько изменил его, чтобы скомпилировать:
public class IntArrayConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string val = value as string;
string[] vals = val.Split(',');
System.Collections.Generic.List<int> ints = new System.Collections.Generic.List<int>();
foreach (string s in vals)
ints.Add(Convert.ToInt32(s));
return ints.ToArray();
}
}
Ответ 3
Мне кажется, что логический — и более расширяемый подход - это взять страницу из элементов управления asp:
:
<uc1:mycontrol runat="server">
<uc1:myintparam>1</uc1:myintparam>
<uc1:myintparam>2</uc1:myintparam>
<uc1:myintparam>3</uc1:myintparam>
</uc1:mycontrol>
Ответ 4
Вы пробовали посмотреть в Преобразователи типов? Эта страница выглядит достойно: http://www.codeguru.com/columns/VB/article.php/c6529/
Кроме того, Spring.Net, похоже, имеет StringArrayConverter (http://www.springframework.net/doc-latest/reference/html/objects-misc.html - раздел 6.4), который, если вы можете его подавать ASP.net, украсив свойство атрибутом TypeConverter, может работать.
Ответ 5
Вы также можете сделать что-то вроде этого:
namespace InternalArray
{
/// <summary>
/// Item for setting value specifically
/// </summary>
public class ArrayItem
{
public int Value { get; set; }
}
public class CustomUserControl : UserControl
{
private List<int> Ints {get {return this.ItemsToList();}
/// <summary>
/// set our values explicitly
/// </summary>
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(List<ArrayItem>))]
public List<ArrayItem> Values { get; set; }
/// <summary>
/// Converts our ArrayItem into a List<int>
/// </summary>
/// <returns></returns>
private List<int> ItemsToList()
{
return (from q in this.Values
select q.Value).ToList<int>();
}
}
}
что приведет к:
<xx:CustomUserControl runat="server">
<Values>
<xx:ArrayItem Value="1" />
</Values>
</xx:CustomUserControl>
Ответ 6
Великий фрагмент @mathieu. Мне нужно было использовать это для преобразования длин, но вместо создания LongArrayConverter я написал версию, использующую Generics.
public class ArrayConverter<T> : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string val = value as string;
if (string.IsNullOrEmpty(val))
return new T[0];
string[] vals = val.Split(',');
List<T> items = new List<T>();
Type type = typeof(T);
foreach (string s in vals)
{
T item = (T)Convert.ChangeType(s, type);
items.Add(item);
}
return items.ToArray();
}
}
Эта версия должна работать с любым типом, который можно конвертировать из строки.
[TypeConverter(typeof(ArrayConverter<int>))]
public int[] Ints { get; set; }
[TypeConverter(typeof(ArrayConverter<long>))]
public long[] Longs { get; set; }
[TypeConverter(typeof(ArrayConverter<DateTime))]
public DateTime[] DateTimes { get; set; }
Ответ 7
Чтобы добавить дочерние элементы, которые делают ваш список, вам нужно настроить ваш контроль определенным образом:
[ParseChildren(true, "Actions")]
[PersistChildren(false)]
[ToolboxData("<{0}:PageActionManager runat=\"server\" ></PageActionManager>")]
[NonVisualControl]
public class PageActionManager : Control
{
Действия выше - это имя свойства c_property, в котором будут находиться дочерние элементы. Я использую ArrayList, поскольку я не тестировал ничего с ним.:
private ArrayList _actions = new ArrayList();
public ArrayList Actions
{
get
{
return _actions;
}
}
когда ваш contorl инициализирован, он будет иметь значения дочерних элементов. Те, которые вы можете сделать мини-класс, который просто содержит ints.
Ответ 8
Сделайте то, о чем говорил Билл со списком, который вам нужен, чтобы создать свойство List в вашем пользовательском элементе управления. Затем вы можете реализовать его, как описано Биллом.
Ответ 9
Вы можете добавить к событиям страницы внутри aspx что-то вроде этого:
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
YourUserControlID.myintarray = new Int32[] { 1, 2, 3 };
}
</script>
Ответ 10
Вы можете реализовать класс конвертера типов, который преобразует между массивами типов int и string.
Затем оформите свойство int array с помощью TypeConverterAttribute, указав класс, который вы внедрили. Затем Visual Studio будет использовать ваш конвертер типов для преобразования типов в ваше свойство.