C# неявное приведение "перегрузка" и проблема отражения

У меня проблема со следующим кодом (который компилируется, но вылетает):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ConsoleApplication1
{
    public struct MyBoolean
    {
        public bool Value { get; set; }

        //cast string -> MyBoolean
        public static implicit operator MyBoolean(System.String value)
        {
            return new MyBoolean() { Value = (value[0] == 'J') };
        }

        //cast bool -> MyBoolean
        public static implicit operator MyBoolean(bool value)
        {
            return new MyBoolean() { Value = value };
        }

        //cast MyBoolean -> bool
        public static implicit operator bool(MyBoolean value)
        {
            return value.Value;
        }
    }

    public class Foo
    {
        public MyBoolean TestProp { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyBoolean myBool = true;        //works

            myBool = "N";   //works

            Foo foo = new Foo();
            foo.TestProp = "J";             //works

            PropertyInfo pi = foo.GetType().GetProperty("TestProp");

            var obj = Convert.ChangeType("J", typeof(MyBoolean));       //throws an InvalidCastException

            pi.SetValue(foo, "J", null);       //throws an ArgumentException

        }
    }
}

Я прокомментировал утверждения, которые не работают. Кто-нибудь знает, почему Convert.ChangeType и PropertyInfo.SetValue, кажется, не используют "перегруженный" оператор приведения, как определено в MyBoolean?

Кстати, я просматривал несколько других документов здесь, но не нашел точного соответствия проблемы.

С наилучшими пожеланиями Томас

2 ответа

Convert.ChangeType() не использует неявные операторы. Вам нужно иметь свой тип реализации MyBoolean IConvertible,

Вторая проблема связана. Пользовательские операторы преобразования не используются. Вам нужно будет преобразовать его вручную, прежде чем передать его SetValue(),

Попробуйте внедрить IConvertible. Convert преобразует ваш экземпляр в этот интерфейс в попытке выполнить преобразование.

Что касается PropertyInfo.SetValue, он получает Set метод собственности. Когда этот метод вызывается через отражение, AFAICT, аргументы проверяются по типу, а не по способности неявно приводиться к нужному типу. Этот каст должен быть выполнен до вызова.

Другие вопросы по тегам