无法从其字符串表示形式创建“System.Object”类型的对象

时间:2011-11-24 16:53:40

标签: c# asp.net webforms

我和webforms解析器今天有一些困难,关于控制属性我希望你们中的一些人可以帮助我!

我有一个名为Value且Control属性的object作为类型。每当我在我的aspx中声明它时,我都会收到错误

  

无法从其字符串创建“System.Object”类型的对象   代表'...'代表'价值'属性。

Wtf,不是所有对象? :)

然后我尝试在我的财产上添加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();
    }
}

TypeConverter

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" />

1 个答案:

答案 0 :(得分:2)

如果添加ValueAsString属性实际上是序列化的属性并阻止Value被序列化呢?

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

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

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

例如,在以下两种情况下(使用VB语法),将创建两个参数,但Param1的值将不存在:

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

为了完整性,这里是我能够实现一个对象转换器而不让ASP.Net在意识到它总是需要一个实际的类来实例化而不仅仅是一个Object之后抛出一个拟合的方式:

首先,创建一个底层逻辑可以实例化的中间类。这个类将为每个可以实现的对象类型类都有一个构造函数:

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);
}

最后,在Param对象中,修改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;
        }
    }
}

我想可能有可能生成动态类或构造函数或对象转换器类,但这不是我所经历过的,所以我无法真正谈论这是否是一个可行的解决方案。< / p>

总而言之,这种方法存在两个问题:

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

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