Skip to content

Convertible Support

Cy Scott edited this page Sep 19, 2021 · 2 revisions

If an interface inherits the ISupportConversion interface then it can be converted to another interface inherits the ISupportConversion interface. Converting one type to another works by using .Net's Convert.ChangeType static method. Here is a simple example of how it works:

[Generate]
public interface IHaveASimpleProperty : ISupportConversion
{
    DateTime DateTime { get; set; }
    Guid Id { get; set; }
    int Integer { get; set; }
    string String { get; set; }
}

The generated code will look like:

public class HaveASimplePropertyModel : IHaveASimpleProperty
{
    public System.DateTime DateTime
    {
        get
        {
            return _DateTime;
        }
        set
        {
            _DateTime = value;
        }
    }
    private System.DateTime _DateTime;
        
    public System.Guid Id
    {
        get
        {
            return _Id;
        }
        set
        {
            _Id = value;
        }
    }
    private System.Guid _Id;
        
    public int Integer
    {
        get
        {
            return _Integer;
        }
        set
        {
            _Integer = value;
        }
    }
    private int _Integer;
        
    public string String
    {
        get
        {
            return _String;
        }
        set
        {
            _String = value;
        }
    }
    private string _String;
        
    public HaveASimplePropertyModel()
    {
    }
        
    protected HaveASimplePropertyModel([System.Diagnostics.CodeAnalysis.NotNullAttribute]ISupportConversion obj)
    {
        if (obj == null) throw new System.ArgumentNullException("obj");
            
        object? value;
            
        this._DateTime = !obj.TryGetValue("DateTime", out value) ? default : value as System.DateTime? ?? (System.DateTime)System.ComponentModel.TypeDescriptor.GetConverter(typeof(System.DateTime)).ConvertFrom(value);
        this._Id = !obj.TryGetValue("Id", out value) ? default : value as System.Guid? ?? (System.Guid)System.ComponentModel.TypeDescriptor.GetConverter(typeof(System.Guid)).ConvertFrom(value);
        this._Integer = !obj.TryGetValue("Integer", out value) ? default : value as int? ?? (int)System.ComponentModel.TypeDescriptor.GetConverter(typeof(int)).ConvertFrom(value);
        this._String = !obj.TryGetValue("String", out value) ? default : value as string ?? value?.ToString();
    }
        
    System.TypeCode System.IConvertible.GetTypeCode() => System.TypeCode.Object;
    bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw new System.NotSupportedException();
    byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw new System.NotSupportedException();
    char System.IConvertible.ToChar(System.IFormatProvider provider) => throw new System.NotSupportedException();
    System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) => throw new System.NotSupportedException();
    decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) => throw new System.NotSupportedException();
    double System.IConvertible.ToDouble(System.IFormatProvider provider) => throw new System.NotSupportedException();
    short System.IConvertible.ToInt16(System.IFormatProvider provider) => throw new System.NotSupportedException();
    int System.IConvertible.ToInt32(System.IFormatProvider provider) => throw new System.NotSupportedException();
    long System.IConvertible.ToInt64(System.IFormatProvider provider) => throw new System.NotSupportedException();
    sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) => throw new System.NotSupportedException();
    float System.IConvertible.ToSingle(System.IFormatProvider provider) => throw new System.NotSupportedException();
    string System.IConvertible.ToString(System.IFormatProvider provider) => ToString();
    ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw new System.NotSupportedException();
    uint System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw new System.NotSupportedException();
    ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw new System.NotSupportedException();
    object System.IConvertible.ToType(System.Type conversionType, System.IFormatProvider provider)
    {
        foreach (var constructor in conversionType.GetConstructors(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic))
        {
            var parameters = constructor.GetParameters();
            if (parameters.Length == 1 && parameters[0].ParameterType.IsAssignableFrom(typeof(MGen.ISupportConversion)))
            {
                return constructor.Invoke(new object[] { this });
            }
        }
        throw new System.InvalidCastException();
    }
        
    bool MGen.ISupportConversion.TryGetValue(string name, out object? value)
    {
        switch (name)
        {
            default:
                value = null;
                return false;
            case "DateTime":
                value = _DateTime;
                return true;
            case "Id":
                value = _Id;
                return true;
            case "Integer":
                value = _Integer;
                return true;
            case "String":
                value = _String;
                return true;
        }
    }
}

You can convert IHaveASimpleProperty to any class or interface that has a generated class that inherits the ISupportConversion interface. Here is a interface that has a generated class:

[Generate]
public interface IHaveCommonPropertiesAsStringsToSimpleProperty : ISupportConversion
{
    string DateTime { get; set; }
    string Id { get; set; }
    string Integer { get; set; }
    string String { get; set; }
}

You can convert the class using this method:

IHaveASimpleProperty instance = new HaveASimplePropertyModel();
IHaveCommonPropertiesAsStringsToSimpleProperty copy = (IHaveCommonPropertiesAsStringsToSimpleProperty)Convert.ChangeType(instance, typeof(IHaveCommonPropertiesAsStringsToSimpleProperty));

Notice that the conversion process will convert property values from one type to another.

Clone this wiki locally