You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行时未知枚举类型如何创建返回其底层int值的get/set访问委托

解决方案

错误原因

你遇到的报错是因为CLR要求Delegate.CreateDelegate创建的委托签名必须与属性的get/set方法签名完全匹配,枚举类型和其底层int属于不同的类型,不允许直接隐式转换委托类型。

实现方案

方案1:委托包装(易维护实现)

通过创建类型匹配的枚举委托,再加一层转换逻辑得到int类型的访问委托,实现简单兼容性好:

public static class DelegateHelper
{
    public static (Func<int> getter, Action<int> setter) CreateEnumAccessors(object instance, PropertyInfo property)
    {
        if (!property.PropertyType.IsEnum)
            throw new ArgumentException("属性必须为枚举类型");
        
        var genericMethod = typeof(DelegateHelper)
            .GetMethod(nameof(CreateEnumAccessorsGeneric), BindingFlags.NonPublic | BindingFlags.Static)
            .MakeGenericMethod(property.PropertyType);
            
        return ((Func<int>, Action<int>))genericMethod.Invoke(null, new[] { instance, property });
    }

    private static (Func<int> getter, Action<int> setter) CreateEnumAccessorsGeneric<TEnum>(object instance, PropertyInfo property)
        where TEnum : Enum
    {
        // 先创建类型完全匹配的枚举委托
        var getEnum = (Func<TEnum>)Delegate.CreateDelegate(typeof(Func<TEnum>), instance, property.GetGetMethod());
        var setEnum = (Action<TEnum>)Delegate.CreateDelegate(typeof(Action<TEnum>), instance, property.GetSetMethod());
        
        // 加转换层得到int类型委托
        Func<int> getter = () => Convert.ToInt32(getEnum());
        Action<int> setter = val => setEnum((TEnum)Enum.ToObject(typeof(TEnum), val));
        
        return (getter, setter);
    }
}

调用方式如下:

var (getterDelegate, setterDelegate) = DelegateHelper.CreateEnumAccessors(arg, property);
settingObj = new MultipleChoice(multipleChoiceAttribute, getterDelegate, setterDelegate, property.PropertyType);

方案2:表达式树编译(高性能实现)

适合需要批量创建大量委托的场景,性能比委托包装高30%以上:

public static (Func<int> getter, Action<int> setter) CreateEnumAccessorsByExpr(object instance, PropertyInfo property)
{
    if (!property.PropertyType.IsEnum)
        throw new ArgumentException("属性必须为枚举类型");
    
    var instanceExpr = Expression.Constant(instance);
    var propertyExpr = Expression.Property(instanceExpr, property);
    
    // 构造getter: 枚举值转int
    var getConvertExpr = Expression.Convert(propertyExpr, typeof(int));
    var getter = Expression.Lambda<Func<int>>(getConvertExpr).Compile();
    
    // 构造setter: int转枚举后赋值
    var valParam = Expression.Parameter(typeof(int), "val");
    var setConvertExpr = Expression.Convert(valParam, property.PropertyType);
    var assignExpr = Expression.Assign(propertyExpr, setConvertExpr);
    var setter = Expression.Lambda<Action<int>>(assignExpr, valParam).Compile();
    
    return (getter, setter);
}

内容的提问来源于stack exchange,提问作者EmmetOT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 16:06:03