我有一个Enum和一个函数来创建它,String因为我找不到内置的方法来做它
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');
Run Code Online (Sandbox Code Playgroud)
但似乎我必须为每个Enum重写此函数,有没有办法在Enum类型作为参数的情况下编写相同的函数?我试图但我发现我不能投于Enum.
//is something with the following signiture actually possible?
dynamic enumFromString(Type enumType,String value){
}
Run Code Online (Sandbox Code Playgroud)
小智 131
从 Dart 版本 2.15 开始,您可以更方便地通过名称查找枚举值,使用.values.byName或 using .values.asNameMap():
enum Visibility {
visible, collapsed, hidden
}
void main() {
// Both calls output `true`
print(Visibility.values.byName('visible') == Visibility.visible);
print(Visibility.values.asNameMap()['visible'] == Visibility.visible);
}
Run Code Online (Sandbox Code Playgroud)
您可以在官方 Dart 2.15 公告博客文章中阅读有关其他枚举改进的更多信息。
Col*_*son 62
镜子并不总是可用,但幸运的是你不需要它们.这是相当紧凑的,应该做你想要的.
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
Run Code Online (Sandbox Code Playgroud)
修复: 正如评论部分中@frostymarvelous所提到的,这是正确的实现:
Fruit f = Fruit.values.firstWhere((e) => e.toString() == 'Fruit.' + str);
Run Code Online (Sandbox Code Playgroud)
Rya*_*ell 16
这一切都太复杂了,我制作了一个简单的库来完成工作:
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
}
Run Code Online (Sandbox Code Playgroud)
anz*_*ert 14
从 Dart 2.17 开始,您可以使用增强型枚举优雅地解决这个问题。
只需将静态方法添加到您选择的枚举中,如下所示:
enum Example {
example1,
example2,
example3;
static Example? fromName(String name) {
for (Example enumVariant in Example.values) {
if (enumVariant.name == name) return enumVariant;
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样查找枚举:
Example? test = Example.fromName("example1");
print(test); // returns Example.example1
Run Code Online (Sandbox Code Playgroud)
编辑:
另一位用户发布了一个更好的解决方案,不需要添加静态方法。
只需使用内置方法,如下所示:
Example? test2 = Example.values.asNameMap()["example1"];
print(test2); // returns Example.example1
Run Code Online (Sandbox Code Playgroud)
Rob*_*ert 11
使用镜子,您可以强制某些行为。我有两个想法。不幸的是Dart不支持类型化函数:
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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
Visibility.COLLAPSED
Visibility.HIDDEN
Run Code Online (Sandbox Code Playgroud)
小智 11
使用Dart 2.15,我们现在可以做到这一点,这更加干净
// Convert to string
String fruitName = Fruit.banana.name;
// Convert back to enum
Fruit fruit = Fruit.values.byName(fruitName);
print(fruit); // Fruit.banana
assert(fruit == Fruit.banana);
Run Code Online (Sandbox Code Playgroud)
Kri*_*sta 10
Here is an alternative way to @mbartn's approach using extensions, extending the enum itself instead of String.
Faster, but more tedious
// We're adding a 'from' entry just to avoid having to use Fruit.apple['banana'],
// which looks confusing.
enum Fruit { from, apple, banana }
extension FruitIndex on Fruit {
// Overload the [] getter to get the name of the fruit.
operator[](String key) => (name){
switch(name) {
case 'banana': return Fruit.banana;
case 'apple': return Fruit.apple;
default: throw RangeError("enum Fruit contains no value '$name'");
}
}(key);
}
void main() {
Fruit f = Fruit.from["banana"];
print("$f is ${f.runtimeType}"); // Outputs: Fruit.banana is Fruit
}
Run Code Online (Sandbox Code Playgroud)
Less tedius, but slower
If O(n) performance is acceptable you could also incorporate @Collin Jackson's answer:
// We're adding a 'from' entry just to avoid having to use Fruit.apple['banana']
// which looks confusing.
enum Fruit { from, apple, banana }
extension FruitIndex on Fruit {
// Overload the [] getter to get the name of the fruit.
operator[](String key) =>
Fruit.values.firstWhere((e) => e.toString() == 'Fruit.' + key);
}
void main() {
Fruit f = Fruit.from["banana"];
print("$f is ${f.runtimeType}"); // Outputs: Fruit.banana is Fruit
}
Run Code Online (Sandbox Code Playgroud)
我使用这个函数,我认为它很简单,不需要任何类型的“黑客”:
T enumFromString<T>(List<T> values, String value) {
return values.firstWhere((v) => v.toString().split('.')[1] == value,
orElse: () => null);
}
Run Code Online (Sandbox Code Playgroud)
你可以这样使用它:
enum Test {
value1,
value2,
}
var test = enumFromString(Test.value, 'value2') // Test.value2
Run Code Online (Sandbox Code Playgroud)
在最新版本的Dart中,enum可以支持自定义字段和方法。因此,最现代的方法是为名称/标签编写自定义字段和静态解析器函数。
例如:
enum Foo {
a('FIRST'),
b('SECOND'),
c('THIRD'),
unknown('UNKNOWN'); // make sure the last element ends in `;`
final String label; // define a private field
const Foo(this.label); // constructor
static Foo fromString(String label) { // static parser method
return values.firstWhere(
(v) => v.label == label,
orElse: () => Foo.unknown,
);
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
final foo = Foo.fromString('FIRST'); // will get `Foo.a`
Run Code Online (Sandbox Code Playgroud)
Collin Jackson的解决方案对我不起作用,因为Dart将枚举字符串化为字符串EnumName.value而不是value(例如Fruit.apple),并且我试图将字符串值转换为类似于apple而不是Fruit.apple从一开始就转换。
考虑到这一点,这是我针对字符串问题枚举的解决方案
enum Fruit {apple, banana}
Fruit getFruitFromString(String fruit) {
fruit = 'Fruit.$fruit';
return Fruit.values.firstWhere((f)=> f.toString() == fruit, orElse: () => null);
}
Run Code Online (Sandbox Code Playgroud)
你的枚举
enum Day {
monday,
tuesday,
}
Run Code Online (Sandbox Code Playgroud)
添加这个扩展(需要一个 import 'package:flutter/foundation.dart';)
extension EnumEx on String {
Day toEnum() => Day.values.firstWhere((d) => describeEnum(d) == toLowerCase());
}
Run Code Online (Sandbox Code Playgroud)
用法:
void main() {
String s = 'monday'; // String
Day monday = s.toEnum(); // Converted to enum
}
Run Code Online (Sandbox Code Playgroud)
我的解决方案与Rob C的解决方案相同,但没有字符串插值:
T getEnumFromString<T>(Iterable<T> values, String value) {
return values.firstWhere((type) => type.toString().split(".").last == value,
orElse: () => null);
}
Run Code Online (Sandbox Code Playgroud)
您可以像下面这样编写getEnum,getEnum将遍历枚举值并返回等于所需字符串的第一个枚举。
Sample getEnum(String name) => Sample.values.firstWhere(
(v) => v.name.toLowerCase() == name.toLowerCase(),
orElse: () => throw Exception('Enum value not found.'),
);
enum SampleEnum { first, second, third }
Run Code Online (Sandbox Code Playgroud)
更新
另外,你可以使用这个:
final SampleEnum nameEnum = SampleEnum.values.byName('second'); // SampleEnum.second
Run Code Online (Sandbox Code Playgroud)
用法:
void main() {
print(getEnum('first'));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15298 次 |
| 最近记录: |