Type casting does not work, although I have implicit statements

I wrote my own type with an implicit casting operator

public class TcBool : TcDataTypeBase
{
    public TcBool() : base(1, false) { } //For somewhat reason without this callin new TcBool() fails
    public TcBool(bool value = false) : base(1, value) { }

    public static implicit operator bool(TcBool var) => (bool)var.Value;

    public static implicit operator TcBool(bool value) => new TcBool(value);
}

public abstract class TcDataTypeBase
{
    public readonly byte Size;
    public readonly object Value;

    public string Name { get; set; }
    public int IndexGroup { get; set; }
    public int IndexOffset { get; set; }

    internal TcDataTypeBase(byte size, object value)
    {
        Size = size;
        Value = value;
    }

    internal TcDataTypeBase(string name, byte size, object value) : this(size, value)
    {
        Name = name;
    }
}

Then, when I try to write it to a boolean property of an object using PropertyInfo.SetValue (), it throws an exception saying that it cannot drop TcBool in System.Boolean.

Is there something stopping reflection mechanisms from using implicit conversion, or am I missing something?

+4
source share
3 answers

The compiler does not know that it needs to do something because SetValue accepts objectwhich is compatible with the type TcBoolwithout any garbage (and, indeed, you cannot define an implicit translation operator for the type of the ancestor). To force a throw, you can do this:

property.SetValue(instance, (bool)TcBool);

, SetValue.

+5

. , , . , , PropertyInfo.SetValue object, .

+1

: , , .


, , "op_Implicit" .

So, I created this (rather long) and hacky helper method that converts a type TObjectobject to a type object TTo, taking into account the implicit conversion operators:

public static object Convert<TObject, TTo>(TObject obj)
{
    IEnumerable<MethodInfo> implicitConversionOperators = obj.GetType()
                                                             .GetMethods()
                                                             .Where(mi => mi.Name == "op_Implicit");
    MethodInfo fittingImplicitConversionOperator = null;

    foreach (MethodInfo methodInfo in implicitConversionOperators)
    {
        if (methodInfo.GetParameters().Any(parameter => parameter.ParameterType == typeof(TObject)))
        {
            fittingImplicitConversionOperator = methodInfo;
        }
    }

    if (fittingImplicitConversionOperator != null)
    {
        return fittingImplicitConversionOperator.Invoke(null, new object[] {obj});
    }

    return (TTo) System.Convert.ChangeType(obj, typeof(TTo));
}

Of course, it is far from perfect, but it can be used like this.

propertyInfo.SetValue(this, Helper.Convert<TcBool, bool>(new TcBool(true)));

to set the property. Of course, if you do not know the types at compile time / do not want this to be detailed information, you can try dynamic, etc., as shown in other answers.

+1
source

Source: https://habr.com/ru/post/1695141/


All Articles