Flutter现代命名风格插件nameof_modern的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter现代命名风格插件nameof_modern的使用

标题

Nameof Modern

内容

在某些情况下,项目需要访问编程语言实体的名字,如方法、属性、构造函数等。不幸的是,今天Flutter没有为这个目的设计的反射机制。但是有代码生成!这个包使用代码生成来帮助访问类、方法等实体的名字。这个包是原始包nameof的更新版。nameof_modern完全基于nameof代码,感谢nameof作者❤️。nameof_modern进行了更新,并且包含了最新的功能以确保新2024和未来项目的正常运行。这个包是新的,并且在社区的帮助下我们正在改进它❤️。

🗒️重要提示: 这个包是基于nameof包创建的。nameof是一个为Dart类成员(如字段、属性、方法和构造函数)生成名称的生成器。nameof_modern完全基于nameof代码,感谢nameof作者❤️。

安装指南

为了使用nameof_modern,你需要你的典型build_runner代码生成设置。 首先,安装build_runnernameof_modern,并将其添加到你的pubspec.yaml文件中:

  • 如果你正在创建一个Flutter项目:

    $ flutter pub add nameof_annotation_modern
    $ flutter pub add --dev build_runner
    $ flutter pub add --dev nameof_modern
    
  • 如果你正在创建一个Dart项目:

    $ dart pub add nameof_annotation_modern
    $ dart pub add --dev build_runner
    $ dart pub add --dev nameof_modern
    

这将安装三个包:

  • build_runner,用于运行代码生成器的工具
  • nameof_modern,代码生成器
  • nameof_annotation,包含nameof_modern注解的包。

运行代码生成器

要运行代码生成器,请执行以下命令:

dart run build_runner build

对于Flutter项目,你也可以运行:

flutter pub run build_runner build

请注意,像大多数代码生成器一样,nameof_modern需要你导入注解(nameof_annotation_modern)并使用part关键字在文件顶部。

例如,一个想要使用nameof_modern的文件将从以下开始:

import 'package:nameof_annotation_modern/nameof_annotation_modern.dart';

part 'my_file.nameof.dart';

使用nameof_modern

简单使用

例如我们有一个类Movie。为了生成这个类的名字,你需要告诉生成器一些指令使用nameof_modern注解:

@nameof
class Movie {
  final String title;
  final String description;
  final int year;
  final String coverUrl;

  Movie(this.title, this.description, this.year, this.coverUrl);
}

然后你需要运行生成器。

它将生成以下代码:

/// Container for names of elements belonging to the [Movie] class
abstract class NameofMovie {
  static const String className = 'Movie';

  static const String constructor = '';

  static const String fieldTitle = 'title';
  static const String fieldDescription = 'description';
  static const String fieldYear = 'year';
  static const String fieldCoverUrl = 'coverUrl';
}

然后在你的代码中使用它:

print(NameofMovie.fieldTitle);
print(NameofMovie.fieldDescription);
print(NameofMovie.fieldYear);
print(NameofMovie.fieldCoverUrl);

很简单!

你也可以为抽象类和混入使用nameof注解。

模型覆盖

你可以通过使用覆盖设置和@NameofIgnore注解非常精确地设置模型成员的覆盖。例如,下面两种配置将导致相同的输出。

  • 第一种配置:
    [@Nameof](/user/Nameof)(coverage: Coverage.excludeImplicit)
    class Movie {
      final String title;
      final String description;
      @nameofKey
      final int year;
      @nameofKey
      final String coverUrl;
    
      Movie(this.title, this.description, this.year, this.coverUrl);
    }
    
  • 第二种配置:
    [@Nameof](/user/Nameof)(coverage: Coverage.includeImplicit)
    class Movie {
      @nameofIgnore
      final String title;
      @nameofIgnore
      final String description;
    
      final int year;
    
      final String coverUrl;
      
      @nameofIgnore
      Movie(this.title, this.description, this.year, this.coverUrl);
    }
    
    输出:
    /// Container for names of elements belonging to the [Movie] class
    abstract class NameofMovie {
      static const String className = 'Movie';
    
      static const String fieldYear = 'year';
      static const String fieldCoverUrl = 'coverUrl';
    }
    
    注意coverage设置,@nameofKey@nameofIgnore注解。 如果你不设置覆盖,则生成器将默认使用includeImplicit设置。
覆盖名称

如果你想覆盖元素的名称,可以这样做! 代码:

@nameof
class Ephemeral {
  @NameofKey(name: 'AbRaCadabra')
  String get flushLight => 'Purple';
}

生成器输出:

/// Container for names of elements belonging to the [Ephemeral] class
abstract class NameofEphemeral {
  static const String className = 'Ephemeral';

  static const String constructor = ''

  static const String propertyGetFlushLight = 'AbRaCadabra'
}

如你所见,属性被重命名了。输出中的名称是AbRaCadabra而不是flushLight

名称目标

@NameofKey注解应用于公共字段、方法、属性和构造函数。

配置

nameof提供了多种自定义生成代码的方法。例如,你可能希望更改模型的覆盖行为。

要实现这一点,有两种可能性:

更改特定模型的行为

如果你想只针对一个特定的类自定义生成代码,可以通过注解设置来实现:

[@Nameof](/user/Nameof)(coverage: Coverage.excludeImplicit
class Employee {...}
更改整个项目的整体行为

相反,如果你不想对单个类进行修改,你可能希望同时对所有nameof模型进行修改。

你可以通过自定义名为build.yaml的文件来实现这一点。这个文件应该放在你的pubspec.yaml文件旁边:

project_folder/
  pubspec.yaml
  build.yaml
  lib/

在那里,你可以通过编写:

targets:
  $default:
    builders:
      nameof:
        options:
          coverage: includeImplicit

更多关于Flutter现代命名风格插件nameof_modern的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter现代命名风格插件nameof_modern的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用nameof_modern插件的一个示例。nameof_modern插件允许你获取变量、类、函数等的字符串名称,这在调试或生成动态UI时非常有用。尽管Dart本身并不原生支持类似C#的nameof运算符,但nameof_modern插件通过宏和构建时代码生成提供了类似的功能。

首先,确保你已经在pubspec.yaml文件中添加了nameof_modern依赖:

dependencies:
  flutter:
    sdk: flutter
  nameof_modern: ^最新版本号 # 替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你可以在你的Flutter项目中使用nameof_modern。以下是一个简单的示例,展示了如何获取变量和函数的名称:

import 'package:flutter/material.dart';
import 'package:nameof_modern/nameof_modern.dart';

part 'main.nameof.g.dart'; // 引入生成的文件

@NameOfClass() // 标记类以生成名称
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    String appName = 'Flutter App'; // 要获取名称的变量
    
    return MaterialApp(
      title: getNameOf(appName), // 获取变量名称
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text(getNameOf(appName)),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '${getNameOf(_incrementCounter)} button pressed ${_counter} times',
                style: Theme.of(context).textTheme.headline4,
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ),
      ),
    );
  }

  int _counter = 0;

  @NameOfFunction() // 标记函数以生成名称
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
}

void main() {
  // 生成名称的代码(通常在构建脚本中自动运行)
  generateNameOfFile(MyApp);
  runApp(MyApp());
}

注意:上面的代码中有几个重要的点需要注意:

  1. part 'main.nameof.g.dart';:这是生成的代码文件的引入。实际使用时,你需要确保在构建过程中生成这个文件。这通常是通过构建脚本或IDE插件自动完成的。

  2. @NameOfClass()@NameOfFunction():这些注解用于标记类和函数,以便nameof_modern插件可以生成它们的名称。但是,请注意,nameof_modern插件的具体API和使用方式可能会根据版本有所不同。上述注解和用法是基于假设的,因为实际的nameof_modern插件可能需要不同的配置或使用方式。

  3. generateNameOfFile(MyApp);:这是一个假设的函数调用,用于生成包含名称信息的代码。在实际使用中,你需要根据nameof_modern插件的文档来配置构建脚本或IDE,以便在构建过程中自动生成这些文件。

由于nameof_modern插件的具体实现和API可能会随着版本更新而变化,因此强烈建议查阅该插件的官方文档和示例代码,以确保正确理解和使用。如果插件提供了命令行工具或构建脚本示例,请按照提供的指南进行配置。

回到顶部