C# 消除开关要求

C# 消除开关要求,c#,object,switch-statement,C#,Object,Switch Statement,我的案例值文本始终等于代码中的相关OSResultStruct,这与我现在实现它的方式和工作方式相同。因此,例如,如果案例为osedition,则属性为OSResultStruct.osedition 是否可以执行以下代码行这样的操作?如果是这样,那么我可以用一行代码替换switch语句 lstNewItems[i].sItemValue = OSresult.OSResultStruct."lstNewItems[i].sItemName.ToString().ToUpper()"; 我现在

我的案例值文本始终等于代码中的相关OSResultStruct,这与我现在实现它的方式和工作方式相同。因此,例如,如果案例为osedition,则属性为OSResultStruct.osedition

是否可以执行以下代码行这样的操作?如果是这样,那么我可以用一行代码替换switch语句

lstNewItems[i].sItemValue = OSresult.OSResultStruct."lstNewItems[i].sItemName.ToString().ToUpper()";
我现在已经实现了,并且正在发挥作用

尝试反射:-

OSresult.OSResultStruct.GetType().GetProperty(lstNewItems[i].sItemName,BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(OSresult.OSResultStruct, null)
对于更通用的方法:-

定义扩展类:-

public static class ClassExtensions
    {
        public static TRes GetPublicPropertyValue<T,TRes>(this T queryObject, string propertyMatch) 
            where T : class,new()
            where TRes : new()

        {
            return (TRes)typeof(T).GetProperty(propertyMatch, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(queryObject, null);
        }
    }
将其用于任何可实例化类型,如下所示:-

OSresult.OSResultStruct.GetPublicPropertyValue<yourtype,yourreturntype>(attribName);

您可以使用反射-按名称获取属性访问器。获取属性访问器时,您需要指定,因为您的名称似乎都是小写,而不是使用访问器的属性的名称。

不会更短,但。。。您可以编写和扩展method和attribute。然后将该属性添加到每个枚举成员中,并通过属性中的字符串对其进行解析。这将使它成为一行并可重复使用

一些澄清代码——正如我所说,它不会很短:

private static readonly Dictionary<DriveTrain, DriveTrainKind> DriveTrainKindMap = 
    Enums.GetValues<DriveTrain>().ToDictionary(d => d, d => d.GetDriveTrainKind());

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class DriveTrainKindAttribute : Attribute
{
    public DriveTrainKindAttribute(DriveTrainKind kind)
    {
        Kind = kind;
    }

    public DriveTrainKind Kind { get; private set; }
}

public static class ExtensionMethods
{
    public static DriveTrainKind GetDriveTrainKind(this DriveTrain value)
    {
        var fieldInfo = typeof(DriveTrain).GetField(value.ToString());
        var attributes = fieldInfo.GetCustomAttributes(typeof(DriveTrainKindAttribute), false)
                                  .Cast<DriveTrainKindAttribute>();
        return attributes.Select(a => a.Kind).SingleOrDefault();
    }
}

public enum DriveTrainKind : byte
{
    ConventionalOrHybrid = 0,
    PluginHybrid = 1,
    BatteryElectric = 2,
}

public enum DriveTrain : short 
{
    [Description("konv_otto"), DriveTrainKind(DriveTrainKind.ConventionalOrHybrid)]
    ConventionalGasoline = 0,

    [Description("konv_diesel"), DriveTrainKind(DriveTrainKind.ConventionalOrHybrid)]
    ConventionalDiesel = 1,
    ...
}

虽然反射很聪明,但编译器不能在编译时检查它,这就是为什么要使用编译语言,对吗?。使用带有属性的扩展方法是编译时检查的。如果属性的数量很大,请实事求是地使用反射,但一定要对所有可能的值进行单元测试。@cfeduke这是正确的。虽然该开关中字符串的正确性也不可在编译时检查。这是我在Java-Enum的C语言中缺少的一个很酷的特性。我也喜欢这个——应该使用反射sparingly@Schultz9999是的,我想没有什么好办法可以绕过神奇的字符串——是的,在Java枚举中,我是从C语言移植过来的Java语言,我喜欢[新的]枚举实现在我执行此操作时一直使用它lstNewItems[i]。sItemValue=OSresult.OSResultStruct.GetType.GetPropertylstNewItems[i]。sItemName.GetValueOSresult.OSResultStruct,null.ToString;我得到的错误对象引用未设置为对象的实例。注意:我添加了该方法。tostringhow i ignorecase应如何按照alexi的建议进行上述操作?请使用绑定标志并参阅GetPropertylstNewItems[i]。sItemName,System.Reflection.BindingFlags.ignorecase否您还需要添加其他标志,因为它将替换默认绑定标志。请看我的答案。我已经更新了它,假设你的财产是公共的。如果不是,你可以使用另一个标志。很高兴它能工作我已经更新了一种更通用的方法。在您的情况下,您可以使用object作为返回类型,因为您要查找的类型是字符串。。。
private static readonly Dictionary<DriveTrain, DriveTrainKind> DriveTrainKindMap = 
    Enums.GetValues<DriveTrain>().ToDictionary(d => d, d => d.GetDriveTrainKind());

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class DriveTrainKindAttribute : Attribute
{
    public DriveTrainKindAttribute(DriveTrainKind kind)
    {
        Kind = kind;
    }

    public DriveTrainKind Kind { get; private set; }
}

public static class ExtensionMethods
{
    public static DriveTrainKind GetDriveTrainKind(this DriveTrain value)
    {
        var fieldInfo = typeof(DriveTrain).GetField(value.ToString());
        var attributes = fieldInfo.GetCustomAttributes(typeof(DriveTrainKindAttribute), false)
                                  .Cast<DriveTrainKindAttribute>();
        return attributes.Select(a => a.Kind).SingleOrDefault();
    }
}

public enum DriveTrainKind : byte
{
    ConventionalOrHybrid = 0,
    PluginHybrid = 1,
    BatteryElectric = 2,
}

public enum DriveTrain : short 
{
    [Description("konv_otto"), DriveTrainKind(DriveTrainKind.ConventionalOrHybrid)]
    ConventionalGasoline = 0,

    [Description("konv_diesel"), DriveTrainKind(DriveTrainKind.ConventionalOrHybrid)]
    ConventionalDiesel = 1,
    ...
}