使用隐式运算符的自定义数据类型不适用于反射

问题描述 投票:0回答:2

我已经使用隐式运算符创建了一个自定义数据类型,下面是示例代码。当我将硬编码值设置为自定义数据类型时,其按预期方式工作,但是使用反射抛出转换错误来设置值。(System.ArgumentException:'类型为'System.String'的对象不能转换为类型'TF.DataType.TFDiplay'。']

有人可以帮助我进行必要的更改以使其在思考中很好地工作

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TF.DataType
{
    public class TFDiplay 
    {
        public TFDiplay() { }
        public TFDiplay(object value, string text) { Value = value; Text = text; }
        public TFDiplay(object value)
        {
            Value = value;
        }

        public static implicit operator TFDiplay(string value)
        {
            var result = new TFDiplay()
            {
                Value = value
            };
            return result;
        }

        public static implicit operator TFDiplay(int value)
        {
            var result = new TFDiplay()
            {
                Value = value
            };
            return result;
        }


        public object Value { get; set; }

        public string Text { get; set; }


    }
}

class Program
{
    static void Main(string[] args)
    {

        TFDiplay tFDiplay;

        tFDiplay = "ss"; //Working as expected
        tFDiplay = 1; //Working as expected

        testDatatype t = new testDatatype();

        Type s = t.GetType();

        PropertyInfo p = s.GetProperty("Flag");

        p.SetValue(t, "ss");  //Throwing error



    }

    public class testDatatype
    {
        public TFDiplay Flag { get; set; }
    }
}
c# reflection
2个回答
0
投票

问题是,您不能通过反射将字符串分配给TFDiplay类型。反射不使用隐式转换器。隐式转换器是compiletype。反射是运行时。

突出显示:

TFDiplay tFDiplay;

tFDiplay = "ss"; //Working as expected
tFDiplay = 1; //Working as expected

隐式运算符为您完成工作。每次将字符串或整数分配给tFDiplay时,都会调用该运算符,然后会启动一个新的TFDisplay。因此,对现有对象调用运算符是没有用的。

这也是分配新实例时不必启动新实例的原因。

这里是有效的反射代码:

using System;
using System.Reflection;

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            TFDiplay tFDiplay;

            tFDiplay = "ss"; //Working as expected
            tFDiplay = 1; //Working as expected

            // ----

            // create an instance of testDatatype
            testDatatype testDatatype = new testDatatype();

            Type testDatatypeType = testDatatype.GetType();

            PropertyInfo flagProperty = testDatatypeType.GetProperty("Flag");

            // you need to get the value of the flag..
            var flagInstance = flagProperty.GetValue(testDatatype);

            Type flagType = flagInstance.GetType();

            PropertyInfo valueProperty = flagType.GetProperty("Value");

            valueProperty.SetValue(flagInstance, "ss");  
        }
    }

    public class testDatatype
    {
        // notice that I create an instance here:
        public TFDiplay Flag { get; } = new TFDiplay();
    }

    public class TFDiplay
    {
        public TFDiplay() { }
        public TFDiplay(object value, string text) { Value = value; Text = text; }
        public TFDiplay(object value)
        {
            Value = value;
        }

        public static implicit operator TFDiplay(string value)
        {
            var result = new TFDiplay()
            {
                Value = value
            };
            return result;
        }

        public static implicit operator TFDiplay(int value)
        {
            var result = new TFDiplay()
            {
                Value = value
            };
            return result;
        }


        public object Value { get; set; }

        public string Text { get; set; }


    }
}

0
投票

扩展Jeroen的答案:

隐式运算符会生成一个称为op_Implicit的特殊方法。要使用隐式运算符正确地“广播”,可以使用反射调用该方法:

var op = typeof(TFDiplay).GetMethod("op_Implicit", BindingFlags.Public | BindingFlags.Static, 
    null, new[] { typeof(string) }, null);
tFDiplay = (TFDiplay)op.Invoke(null, new object[] { "ss" });
© www.soinside.com 2019 - 2024. All rights reserved.