2011-11-24 62 views
2

我和web表单解析器现在遇到了麻烦创建类型“System.Object的”的对象的今天,关于控制属性,我希望你们中的一些可以帮我!无法从它的字符串表示

我有一个Controlobject类型名为Value属性。当我每次宣布它在我的aspx时候,我得到的错误

不能创建从‘价值’属性的字符串 表示“...”类型的对象“System.Object的”。

跆拳道,心不是一切对象? :)

然后我尝试对我的财产增加TypeConverter,但没有运气。

我的控制

[ParseChildren(true, "Value")] 
[TypeConverter(typeof(ExpandableObjectConverter))] 
[ControlBuilder(typeof(ParamControlBuilder))] 
public class Param : Control 
{ 
    public string Name { get; set; } 

    [TypeConverter(typeof(StringToObjectConverter))] 
    public object Value { get; set; } 

    protected override void AddParsedSubObject(object obj) 
    { 
     base.AddParsedSubObject(obj); 
    } 

    public override void DataBind() 
    { 
     base.DataBind(); 
    } 

    protected override void DataBindChildren() 
    { 
     base.DataBindChildren(); 
    } 
} 

的类型转换器

public class StringToObjectConverter : TypeConverter 
{ 
    public override bool IsValid(ITypeDescriptorContext context, object value) 
    { 
     return true; 
    } 

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     if (sourceType == typeof(string)) 
     { 
      return true; 
     } 

     return base.CanConvertFrom(context, sourceType); 
    } 

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
    { 
     if (destinationType == typeof(object)) 
     { 
      return true; 
     } 

     if (destinationType == typeof(InstanceDescriptor)) 
     { 
      return true; 
     } 

     return base.CanConvertTo(context, destinationType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     return value.ToString(); 
    } 

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
    { 
     if (destinationType == typeof(object)) 
     { 
      return (object)value; 
     } 

     if (destinationType == typeof(InstanceDescriptor)) 
     { 
      return new InstanceDescriptor(typeof(object).GetConstructor(new Type[] { }), new object[] { }); 
     } 

     return base.ConvertTo(context, culture, value, destinationType); 
    } 
} 

我想要做的是能在我的aspx页面中写入以下

<my:param name="A object" value="<# value_of_a_method()" %> runat="server" /> 
<my:param name="A object" value="this_is_just_a_string" runat="server" /> 

第一个例子工程好吧,第二次失败,提到错误。不,我不能相信,解决这个问题的唯一方法是每次数据绑定,即使是常量字符串像

<my:param name="A object" value='<%# "this_is_just_a_string" %>' runat="server" /> 
+0

该转换器用于控制,而不是属性。那样,如果你使用它作为书面的,它总是反序列化为一个字符串;将一个字符串转换为对象vs将其反序列化为之前的东西有很大的区别。 –

+0

所以我应该基本上创建我自己的Wrapper类,只是持有一个对象,并把一个转换器,可以转换字符串和对象来自我的包装?然后,我的Value属性的类型将是这个包装而不是Object? –

+0

你还没有真正清楚你想要达到什么目的。坚持和重新创造一个只有“对象”的价值,实际上是非常难... –

回答

2

有关添加ValueAsString属性,实际上是被序列化的一个序列化和防止Value什么?

ValueAsString然后将负责适当地(例如XML或JSON序列化)序列化和反序列化Value

更新 事实证明,由于ASP.Net构建控件的方式,没有办法做你想要做的事情。

可以实现一种机制来获取对象类型(如字符串或内部类)以进行处理,但是如果在混合中包含诸如Ints之类的基本类型,框架甚至不会执行TypeConverter for你的对象价值。

例如,在以下两种情况下(使用VB语法),未参数将被创建,但参数1的值将是什么:

<cti:Param ID="Param1" Value="<%# CInt(1) %>" runat="server" /> 
<cti:Param ID="Param2" Value="test" runat="server" /> 

为了完整起见,这里是我如何能够

首先,创建一个中间类底层逻辑可以实例:实现对象转换器而无需ASP.Net意识到它总是需要一个实际类实例化,而不是仅仅一个对象后扔一个合适的。这个类必须为每个对象类型的类可以实现一个构造函数:

public class MyObjectConverter 
{ 
    public MyObjectConverter() : base() 
    { 
    } 
    public MyObjectConverter(string oValue) : this() 
    { 
     this.Value = oValue; 
    } 

    public object Value { get; set; } 

    public override string ToString() 
    { 
     if (this.Value == null) 
     { 
      return string.Empty; 
     } 
     else 
     { 
      return this.Value.ToString(); 
     } 
    } 
} 

接下来,修改StringToObjectConverter的的ConvertTo方法,以便它将使用适当的构造新的类的实例(对象构造仍然混淆这里的代码):

public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
{ 
    if (destinationType == typeof(object)) 
    { 
     return (object)value; 
    } 

    if (destinationType == typeof(InstanceDescriptor)) 
    { 
     return new InstanceDescriptor(typeof(MyObjectConverter).GetConstructor(new Type[] {value.GetType()}), new object[] {value}); 
    } 

    return base.ConvertTo(context, culture, value, destinationType); 
} 

最后,在参数对象,修改Value属性来处理新类型:

private object m_Value; 
[TypeConverter(typeof(StringToObjectConverter))] 
public object Value 
{ 
    get 
    { 
     return m_Value; 
    } 
    set 
    { 
     if (value is MyObjectConverter) 
     { 
      m_Value = ((MyObjectConverter)value).Value; 
     } 
     else 
     { 
      m_Value = value; 
     } 
    } 
} 

我想有可能生成动态类或构造函数或者目标转换器类,但这并不是我所经历的,所以我不能真正说出这是否是一种可行的解决方案。

因此,要总结,有两个问题这种方法:

1)不能使用它原始数据类型。但是,即使使用Object Value属性而不将字符串带入等式也不支持此功能。

2)您必须为您希望支持的所有数据类型明确定义构造函数。

+0

问题是我想匹配一个已经存在的xml格式我尽可能基本上能够复制/粘贴一些标记到一个aspx页面,添加runat =“服务器”,事情应该只是工作, –

+0

更新用一种新的方法和发现来回答。 –

+0

感谢您的更新答案。这与我最后的结果类似,并且我意识到唯一可行的选择就是在aspx标记中支持基本类型,并且强制开发人员在需要绑定复杂类型时切换到Codebehind。我的意思是,这就是Webforms已经为之做的事情。 ListControls中的ListItem,在那里你不能对标记进行任何操作。 –