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条回答
▲ chillily
2楼-- · 2020-02-05 12:38

I think my approach is slightly different, but might be more convenient in some cases. Finally, we have parse and tryParse for enum types:

import 'dart:mirrors';

class Enum {
  static T parse<T>(String value) {
    final T result = (reflectType(T) as ClassMirror).getField(#values)
        .reflectee.firstWhere((v)=>v.toString().split('.').last.toLowerCase() == value.toLowerCase()) as T;
    return result;
  }

  static T tryParse<T>(String value, { T defaultValue }) {
    T result = defaultValue;
    try {
      result = parse<T>(value);
    } catch(e){
      print(e);
    }
    return result;
  }
}

EDIT: this approach is NOT working in the Flutter applications, by default mirrors are blocked in the Flutter because it causes the generated packages to be very large.

查看更多
孤傲高冷的网名
3楼-- · 2020-02-05 12:39

Here is the function that converts given string to enum type:

EnumType enumTypeFromString(String typeString) => EnumType.values
    .firstWhere((type) => type.toString() == "EnumType." + typeString);

And here is how you convert given enum type to string:

String enumTypeToString(EnumType type) => type.toString().split(".")[1];
查看更多
可以哭但决不认输i
4楼-- · 2020-02-05 12:44

My solution is identical to Rob C's solution but without string interpolation:

T getEnumFromString<T>(Iterable<T> values, String value) {
  return values.firstWhere((type) => type.toString().split(".").last == value,
      orElse: () => null);
}
查看更多
老娘就宠你
5楼-- · 2020-02-05 12:44

I improved Collin Jackson's answer using Dart 2.7 Extension Methods to make it more elegant.

enum Fruit { apple, banana }

extension EnumParser on String {
  Fruit toFruit() {
    return Fruit.values.firstWhere(
        (e) => e.toString().toLowerCase() == 'fruit.$this'.toLowerCase(),
        orElse: () => null); //return null if not found
  }
}

main() {
  Fruit apple = 'apple'.toFruit();
  assert(apple == Fruit.apple); //true
}
查看更多
做个烂人
6楼-- · 2020-02-05 12:48

Collin Jackson's solution didn't work for me because Dart stringifies enums into EnumName.value rather than just value (for instance, Fruit.apple), and I was trying to convert the string value like apple rather than converting Fruit.apple from the get-go.

With that in mind, this is my solution for the enum from string problem

enum Fruit {apple, banana}

Fruit getFruitFromString(String fruit) {
  fruit = 'Fruit.$fruit';
  return Fruit.values.firstWhere((f)=> f.toString() == fruit, orElse: () => null);
}
查看更多
贪生不怕死
7楼-- · 2020-02-05 12:49

Using mirrors you could force some behaviour. I had two ideas in mind. Unfortunately Dart does not support typed functions:

import 'dart:mirrors';

enum Visibility {VISIBLE, COLLAPSED, HIDDEN}

class EnumFromString<T> {
  T get(String value) {
    return (reflectType(T) as ClassMirror).getField(#values).reflectee.firstWhere((e)=>e.toString().split('.')[1].toUpperCase()==value.toUpperCase());
  }
}

dynamic enumFromString(String value, t) {
  return (reflectType(t) as ClassMirror).getField(#values).reflectee.firstWhere((e)=>e.toString().split('.')[1].toUpperCase()==value.toUpperCase());
}

void main() {
  var converter = new EnumFromString<Visibility>();

  Visibility x = converter.get('COLLAPSED');
  print(x);

  Visibility y = enumFromString('HIDDEN', Visibility);
  print(y);
}

Outputs:

Visibility.COLLAPSED
Visibility.HIDDEN
查看更多
登录 后发表回答