Enum from String

2020-02-05 11:56发布

I have an Enum and a function to create it from a String because i couldn't find a built in way to do it

enum Visibility{VISIBLE,COLLAPSED,HIDDEN}

Visibility visibilityFromString(String value){
  return Visibility.values.firstWhere((e)=>
      e.toString().split('.')[1].toUpperCase()==value.toUpperCase());
}

//used as
Visibility x = visibilityFromString('COLLAPSED');

but it seems like i have to rewrite this function for every Enum i have, is there a way to write the same function where it takes the Enum type as parameter? i tried to but i figured out that i can't cast to Enum.

//is something with the following signiture actually possible?
     dynamic enumFromString(Type enumType,String value){

     }

标签: dart
13条回答
神经病院院长
2楼-- · 2020-02-05 12:29

You can add an extension, it will still be accessed from the enum!

usage example: this answer

查看更多
来,给爷笑一个
3楼-- · 2020-02-05 12:33

I had the same problem with building objects from JSON. In JSON values are strings, but I wanted enum to validate if the value is correct. I wrote this helper which works with any enum, not a specified one:

class _EnumHelper {


 var cache = {};

  dynamic str2enum(e, s) {
    var o = {};
    if (!cache.containsKey(e)){
      for (dynamic i in e) {
        o[i.toString().split(".").last] = i;
      }
      cache[e] = o;
    } else {
      o = cache[e];
    }
    return o[s];
  }
}

_EnumHelper enumHelper = _EnumHelper();

Usage:

enumHelper.str2enum(Category.values, json['category']);

PS. I did not use types on purpose here. enum is not type in Dart and treating it as one makes things complicated. Class is used solely for caching purposes.

查看更多
倾城 Initia
4楼-- · 2020-02-05 12:34

There are a couple of enums packages which allowed me to get just the enum string rather than the type.value string (Apple, not Fruit.Apple).

https://pub.dartlang.org/packages/built_value (this is more up to date)

https://pub.dartlang.org/packages/enums

void main() {
  print(MyEnum.nr1.index);            // prints 0
  print(MyEnum.nr1.toString());       // prints nr1
  print(MyEnum.valueOf("nr1").index); // prints 0
  print(MyEnum.values[1].toString())  // prints nr2
  print(MyEnum.values.last.index)     // prints 2
  print(MyEnum.values.last.myValue);  // prints 15
}  
查看更多
5楼-- · 2020-02-05 12:36

This is all so complicated I made a simple library that gets the job done:

https://pub.dev/packages/enum_to_string

import 'package:enum_to_string:enum_to_string.dart';

enum TestEnum { testValue1 };

convert(){
    String result = EnumToString.parse(TestEnum.testValue1);
    //result = 'testValue1'

    String resultCamelCase = EnumToString.parseCamelCase(TestEnum.testValue1);
    //result = 'Test Value 1'

    final result = EnumToString.fromString(TestEnum.values, "testValue1");
    // TestEnum.testValue1
}
查看更多
6楼-- · 2020-02-05 12:36

@Collin Jackson has a very good answer IMO. I had used a for-in loop to achieve a similar result prior to finding this question. I am definitely switching to using the firstWhere method.

Expanding on his answer this is what I did to deal with removing the type from the value strings:

enum Fruit { apple, banana }

class EnumUtil {
    static T fromStringEnum<T>(Iterable<T> values, String stringType) {
        return values.firstWhere(
                (f)=> "${f.toString().substring(f.toString().indexOf('.')+1)}".toString()
                    == stringType, orElse: () => null);
    }
}

main() {
    Fruit result = EnumUtil.fromStringEnum(Fruit.values, "apple");
    assert(result == Fruit.apple);
}

Maybe someone will find this useful...

查看更多
爷、活的狠高调
7楼-- · 2020-02-05 12:38

Mirrors aren't always available, but fortunately you don't need them. This is reasonably compact and should do what you want.

enum Fruit { apple, banana }

// Convert to string
String str = Fruit.banana.toString();

// Convert to enum
Fruit f = Fruit.values.firstWhere((e) => e.toString() == str);

assert(f == Fruit.banana);  // it worked

Fix: As mentioned by @frostymarvelous in the comments section, this is correct implementation:

Fruit f = Fruit.values.firstWhere((e) => e.toString() == 'Fruit.' + str);
查看更多
登录 后发表回答