c# - 无法从其字符串表示形式创建类型为 'System.Object' 的对象

标签 c# asp.net webforms

我和 webforms 解析器今天遇到了一些困难,关于控件属性我希望你们中的一些人能帮助我!

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

Cannot create an object of type 'System.Object' from its string representation '...' for the 'Value' property.

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

类型转换器

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

第一个示例工作正常,第二个示例失败并出现上述错误。不,我不敢相信解决这个问题的唯一方法是每次都进行数据绑定(bind),即使对于像

这样的常量字符串也是如此
<my:param name="A object" value='<%# "this_is_just_a_string" %>' runat="server" />

最佳答案

如何添加一个 ValueAsString 属性,它实际上是序列化的属性并防止 Value 被序列化?

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

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

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

例如,在下面两种情况下(使用VB语法),两个Params都会被创建,但是Param1的Value将为空:

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

最后,在 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;
        }
    }
}

我想可能可以生成动态类或构造函数或对象转换器类,但我没有这方面的经验,所以我无法确定这是否是一个可行的解决方案。

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

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

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

关于c# - 无法从其字符串表示形式创建类型为 'System.Object' 的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8260343/

相关文章:

c# - 将对象数组转换为连接的字符串

c# - 哪个是重定向 URL 的最佳方式?我们应该使用 Response.Redirect 还是有其他重定向命令?

c# - 如何让 C# 计时器在创建它的同一线程上执行?

c# - 是否在 ASP.Net 应用程序中锁定单例公共(public)方法

asp.net-mvc-4 - 多个 RequiredFieldValidator 崩溃页面

javascript - 如何在母版页和单个页面上应用 KnockoutJS?

c# - 使用 linq 合并集合

asp.net - 如何指定 ASP.NET 主题不应应用于特定文件夹?

c# - Telerik TopPane 高度自动?

c# - 为什么我无法显示这个特定的#变量值?