如何将Abp框架融入.NET MAUI项目配置及基类编写步骤详解?

2026-05-25 04:371阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1767个文字,预计阅读时间需要8分钟。

如何将Abp框架融入.NET MAUI项目配置及基类编写步骤详解?

由于我们需要开发一个数据持久化型的小应用,并在完成Abp功能集成后进行数据库相关配置,我们需在MauiBoilerplate.Core项目中添加两个实体类:配置数据库和设置数据库。以下是简化的步骤:

1. 配置数据库: - 添加一个实体类,例如`DatabaseConfiguration`,用于存储数据库连接字符串等信息。

2. 设置数据库: - 添加另一个实体类,例如`DatabaseSettings`,用于存储数据库初始化和配置参数。

csharppublic class DatabaseConfiguration{ public string ConnectionString { get; set; } // 其他配置属性}

public class DatabaseSettings{ public DatabaseConfiguration Configuration { get; set; } // 初始化和配置参数}

因为我们要做一个数据持久化型的小应用,所以在完成Abp功能的集成后,我们需要做数据库相关的配置工作

配置数据库

在MauiBoilerplate.Core项目中,添加两个实体类:

我们简单的写一个歌曲(song)的实体类

其中包含了歌曲标题(MusicTitle),艺术家(Artist),专辑(Album),时长(Duration)以及发售日期(ReleaseDate)

public class Song : FullAuditedEntity<long> { [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public override long Id { get; set; } public string MusicTitle { get; set; } public string Artist { get; set; } public string Album { get; set; } public TimeSpan Duration { get; set; } public DateTime ReleaseDate { get; set; } }

在MauiBoilerplate.EntityFrameworkCore项目中:将这个类添加至MauiBoilerplateDbContext中

public class MauiBoilerplateDbContext : AbpDbContext { //Add DbSet properties for your entities... public DbSet<Song> Song { get; set; } }

新建WithDbContextHelper.cs

创建一个静态类WithDbContext,利用Abp的工作单元模式对dbcontext执行操作

public class WithDbContextHelper { public static void WithDbContext<TDbContext>(IIocResolver iocResolver, Action<TDbContext> contextAction) where TDbContext : DbContext { using (var uowManager = iocResolver.ResolveAsDisposable<IUnitOfWorkManager>()) { using (var uow = uowManager.Object.Begin(TransactionScopeOption.Suppress)) { var context = uowManager.Object.Current.GetDbContext<TDbContext>(); contextAction(context); uow.Complete(); } } } }

[可选]种子数据相关类编写

编写种子数据帮助类SeedHelper.cs,与数据库初始化类InitialDbBuilder,这里将在程序启动时向数据库插入一些种子数据

public static class SeedHelper { public static void SeedHostDb(IIocResolver iocResolver) { Helper.WithDbContextHelper.WithDbContext<MauiBoilerplateDbContext>(iocResolver, SeedHostDb); } public static void SeedHostDb(MauiBoilerplateDbContext context) { context.SuppressAutoSetTenantId = true; // Host seed new InitialDbBuilder(context).Create(); } }

编写MauiBoilerplateEntityFrameworkCoreModule.cs

[DependsOn( typeof(MauiBoilerplateCoreModule), typeof(AbpEntityFrameworkCoreModule))] public class MauiBoilerplateEntityFrameworkCoreModule : AbpModule { public bool SkipDbContextRegistration { get; set; } public bool SkipDbSeed { get; set; } public override void PreInitialize() { if (!SkipDbContextRegistration) { Configuration.Modules.AbpEfCore().AddDbContext<MauiBoilerplateDbContext>(options => { if (options.ExistingConnection != null) { DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ExistingConnection); } else { DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ConnectionString); } }); } } public override void Initialize() { IocManager.RegisterAssemblyByConvention(typeof(MauiBoilerplateEntityFrameworkCoreModule).GetAssembly()); } public override void PostInitialize() { Helper.WithDbContextHelper.WithDbContext<MauiBoilerplateDbContext>(IocManager, RunMigrate); if (!SkipDbSeed) { SeedHelper.SeedHostDb(IocManager); } } public static void RunMigrate(MauiBoilerplateDbContext dbContext) { dbContext.Database.Migrate(); } }

将MauiBoilerplate.EntityFrameworkCore设置为启动项目,选择框架为.net6.0

打开程序包管理器控制台,选择默认项目MauiBoilerplate.EntityFrameworkCore

​编辑

运行Add-Migration命令,将生成迁移脚本

运行MauiBoilerplate.EntityFrameworkCore,将生成mato.db等三个文件,

​编辑

编写基类(可选)

我们在使用相关的父类时,某某ContentPage,或者某某UserControl时,需要像使用AbpServiceBase一样使用一些常用的功能,比如字符串的本地化,配置,AutoMapper对象等,就像AbpServiceBase的注释里描述的那样:

/// <summary>
/// This class can be used as a base class for services.
/// It has some useful objects property-injected and has some basic methods
/// most of services may need to.
/// </summary>

此时,需要编写一个基类(奈何.net本身没有Mixin模式,C#语言也不支持多继承),这些基类仅是注入了一些常用的Manager,方便代码编写者使用,因此基类的创建不是必须的。

比如可以增加一个ContentPageBase类作为ContentPage实例控件的基类

新建ContentPageBase.cs文件,创建类ContentPageBase继承于ContentPage

public class ContentPageBase : ContentPage { public IObjectMapper ObjectMapper { get; set; } /// <summary> /// Reference to the setting manager. /// </summary> public ISettingManager SettingManager { get; set; } /// <summary> /// Reference to the localization manager. /// </summary> public ILocalizationManager LocalizationManager { get; set; } /// <summary> /// Gets/sets name of the localization source that is used in this application service. /// It must be set in order to use <see cref="L(string)"/> and <see cref="L(string,CultureInfo)"/> methods. /// </summary> protected string LocalizationSourceName { get; set; } /// <summary> /// Gets localization source. /// It's valid if <see cref="LocalizationSourceName"/> is set. /// </summary> protected ILocalizationSource LocalizationSource { get { if (LocalizationSourceName == null) { throw new AbpException("Must set LocalizationSourceName before, in order to get LocalizationSource"); } if (_localizationSource == null || _localizationSource.Name != LocalizationSourceName) { _localizationSource = LocalizationManager.GetSource(LocalizationSourceName); } return _localizationSource; } } private ILocalizationSource _localizationSource; /// <summary> /// Constructor. /// </summary> protected ContentPageBase() { LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName; ObjectMapper = NullObjectMapper.Instance; LocalizationManager = NullLocalizationManager.Instance; } /// <summary> /// Gets localized string for given key name and current language. /// </summary> /// <param name="name">Key name</param> /// <returns>Localized string</returns> protected virtual string L(string name) { return LocalizationSource.GetString(name); } /// <summary> /// Gets localized string for given key name and current language with formatting strings. /// </summary> /// <param name="name">Key name</param> /// <param name="args">Format arguments</param> /// <returns>Localized string</returns> protected virtual string L(string name, params object[] args) { return LocalizationSource.GetString(name, args); } /// <summary> /// Gets localized string for given key name and specified culture information. /// </summary> /// <param name="name">Key name</param> /// <param name="culture">culture information</param> /// <returns>Localized string</returns> protected virtual string L(string name, CultureInfo culture) { return LocalizationSource.GetString(name, culture); } /// <summary> /// Gets localized string for given key name and current language with formatting strings. /// </summary> /// <param name="name">Key name</param> /// <param name="culture">culture information</param> /// <param name="args">Format arguments</param> /// <returns>Localized string</returns> protected virtual string L(string name, CultureInfo culture, params object[] args) { return LocalizationSource.GetString(name, culture, args); } }

同理,若我们使用了其他控件类时,可以增加一个Base类作为实例控件的基类的

比如Popup控件,就编写一个PopupBase基类。

在这里我们编写了两个基类

​编辑

本地化配置

新建一个TranslateExtension.cs作为Xaml标签的本地化处理类

[ContentProperty("Text")] public class TranslateExtension : DomainService, IMarkupExtension { public TranslateExtension() { LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName; } public string Text { get; set; } public object ProvideValue(IServiceProvider serviceProvider) { if (Text == null) return ""; var translation = L(Text); return translation; } }

在MauiBoilerplateLocalization.cs配置好SourceFiles

public static void Configure(ILocalizationConfiguration localizationConfiguration) { localizationConfiguration.Sources.Add( new DictionaryBasedLocalizationSource(MauiBoilerplateConsts.LocalizationSourceName, new XmlEmbeddedFileLocalizationDictionaryProvider( typeof(LocalizationConfigurer).GetAssembly(), "MauiBoilerplate.Core.Localization.SourceFiles" ) ) ); } 编写ViewModelBase

为实现Mvvm设计模式,页面需要绑定一个继承于ViewModelBase的类型

在ViewModelBase中,需要实现INotifyPropertyChanged以处理绑定成员变化时候的通知消息;

ViewModelBase集成于AbpServiceBase以方便ViewModel代码编写者使用常用的功能,比如字符串的本地化,配置,AutoMapper对象等。

如何将Abp框架融入.NET MAUI项目配置及基类编写步骤详解?

public abstract class ViewModelBase : AbpServiceBase, ISingletonDependency, INotifyPropertyChanged { public ViewModelBase() { LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName; } public event PropertyChangedEventHandler PropertyChanged; protected PropertyChangedEventHandler PropertyChangedHandler { get; } public void VerifyPropertyName(string propertyName) { Type type = GetType(); if (!string.IsNullOrEmpty(propertyName) && type.GetTypeInfo().GetDeclaredProperty(propertyName) == null) throw new ArgumentException("找不到属性", propertyName); } public virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler propertyChanged = PropertyChanged; if (propertyChanged == null) return; propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression) { if (PropertyChanged == null) return; string propertyName = GetPropertyName(propertyExpression); if (string.IsNullOrEmpty(propertyName)) return; RaisePropertyChanged(propertyName); } protected static string GetPropertyName<T>(Expression<Func<T>> propertyExpression) { if (propertyExpression == null) throw new ArgumentNullException(nameof(propertyExpression)); MemberExpression body = propertyExpression.Body as MemberExpression; if (body == null) throw new ArgumentException("参数不合法", nameof(propertyExpression)); PropertyInfo member = body.Member as PropertyInfo; if (member == null) throw new ArgumentException("找不到属性", nameof(propertyExpression)); return member.Name; } }

至此,我们完成了数据库的配置,内容页基类与ViewModel基类的编写,接下来可以制作我们的页面了。请看下一章将Abp移植进.NET MAUI项目(三):构建UI层 - 林晓lx - 自由互联 (cnblogs.com)

项目地址

jevonsflash/maui-abp-sample (github.com)

本文共计1767个文字,预计阅读时间需要8分钟。

如何将Abp框架融入.NET MAUI项目配置及基类编写步骤详解?

由于我们需要开发一个数据持久化型的小应用,并在完成Abp功能集成后进行数据库相关配置,我们需在MauiBoilerplate.Core项目中添加两个实体类:配置数据库和设置数据库。以下是简化的步骤:

1. 配置数据库: - 添加一个实体类,例如`DatabaseConfiguration`,用于存储数据库连接字符串等信息。

2. 设置数据库: - 添加另一个实体类,例如`DatabaseSettings`,用于存储数据库初始化和配置参数。

csharppublic class DatabaseConfiguration{ public string ConnectionString { get; set; } // 其他配置属性}

public class DatabaseSettings{ public DatabaseConfiguration Configuration { get; set; } // 初始化和配置参数}

因为我们要做一个数据持久化型的小应用,所以在完成Abp功能的集成后,我们需要做数据库相关的配置工作

配置数据库

在MauiBoilerplate.Core项目中,添加两个实体类:

我们简单的写一个歌曲(song)的实体类

其中包含了歌曲标题(MusicTitle),艺术家(Artist),专辑(Album),时长(Duration)以及发售日期(ReleaseDate)

public class Song : FullAuditedEntity<long> { [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public override long Id { get; set; } public string MusicTitle { get; set; } public string Artist { get; set; } public string Album { get; set; } public TimeSpan Duration { get; set; } public DateTime ReleaseDate { get; set; } }

在MauiBoilerplate.EntityFrameworkCore项目中:将这个类添加至MauiBoilerplateDbContext中

public class MauiBoilerplateDbContext : AbpDbContext { //Add DbSet properties for your entities... public DbSet<Song> Song { get; set; } }

新建WithDbContextHelper.cs

创建一个静态类WithDbContext,利用Abp的工作单元模式对dbcontext执行操作

public class WithDbContextHelper { public static void WithDbContext<TDbContext>(IIocResolver iocResolver, Action<TDbContext> contextAction) where TDbContext : DbContext { using (var uowManager = iocResolver.ResolveAsDisposable<IUnitOfWorkManager>()) { using (var uow = uowManager.Object.Begin(TransactionScopeOption.Suppress)) { var context = uowManager.Object.Current.GetDbContext<TDbContext>(); contextAction(context); uow.Complete(); } } } }

[可选]种子数据相关类编写

编写种子数据帮助类SeedHelper.cs,与数据库初始化类InitialDbBuilder,这里将在程序启动时向数据库插入一些种子数据

public static class SeedHelper { public static void SeedHostDb(IIocResolver iocResolver) { Helper.WithDbContextHelper.WithDbContext<MauiBoilerplateDbContext>(iocResolver, SeedHostDb); } public static void SeedHostDb(MauiBoilerplateDbContext context) { context.SuppressAutoSetTenantId = true; // Host seed new InitialDbBuilder(context).Create(); } }

编写MauiBoilerplateEntityFrameworkCoreModule.cs

[DependsOn( typeof(MauiBoilerplateCoreModule), typeof(AbpEntityFrameworkCoreModule))] public class MauiBoilerplateEntityFrameworkCoreModule : AbpModule { public bool SkipDbContextRegistration { get; set; } public bool SkipDbSeed { get; set; } public override void PreInitialize() { if (!SkipDbContextRegistration) { Configuration.Modules.AbpEfCore().AddDbContext<MauiBoilerplateDbContext>(options => { if (options.ExistingConnection != null) { DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ExistingConnection); } else { DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ConnectionString); } }); } } public override void Initialize() { IocManager.RegisterAssemblyByConvention(typeof(MauiBoilerplateEntityFrameworkCoreModule).GetAssembly()); } public override void PostInitialize() { Helper.WithDbContextHelper.WithDbContext<MauiBoilerplateDbContext>(IocManager, RunMigrate); if (!SkipDbSeed) { SeedHelper.SeedHostDb(IocManager); } } public static void RunMigrate(MauiBoilerplateDbContext dbContext) { dbContext.Database.Migrate(); } }

将MauiBoilerplate.EntityFrameworkCore设置为启动项目,选择框架为.net6.0

打开程序包管理器控制台,选择默认项目MauiBoilerplate.EntityFrameworkCore

​编辑

运行Add-Migration命令,将生成迁移脚本

运行MauiBoilerplate.EntityFrameworkCore,将生成mato.db等三个文件,

​编辑

编写基类(可选)

我们在使用相关的父类时,某某ContentPage,或者某某UserControl时,需要像使用AbpServiceBase一样使用一些常用的功能,比如字符串的本地化,配置,AutoMapper对象等,就像AbpServiceBase的注释里描述的那样:

/// <summary>
/// This class can be used as a base class for services.
/// It has some useful objects property-injected and has some basic methods
/// most of services may need to.
/// </summary>

此时,需要编写一个基类(奈何.net本身没有Mixin模式,C#语言也不支持多继承),这些基类仅是注入了一些常用的Manager,方便代码编写者使用,因此基类的创建不是必须的。

比如可以增加一个ContentPageBase类作为ContentPage实例控件的基类

新建ContentPageBase.cs文件,创建类ContentPageBase继承于ContentPage

public class ContentPageBase : ContentPage { public IObjectMapper ObjectMapper { get; set; } /// <summary> /// Reference to the setting manager. /// </summary> public ISettingManager SettingManager { get; set; } /// <summary> /// Reference to the localization manager. /// </summary> public ILocalizationManager LocalizationManager { get; set; } /// <summary> /// Gets/sets name of the localization source that is used in this application service. /// It must be set in order to use <see cref="L(string)"/> and <see cref="L(string,CultureInfo)"/> methods. /// </summary> protected string LocalizationSourceName { get; set; } /// <summary> /// Gets localization source. /// It's valid if <see cref="LocalizationSourceName"/> is set. /// </summary> protected ILocalizationSource LocalizationSource { get { if (LocalizationSourceName == null) { throw new AbpException("Must set LocalizationSourceName before, in order to get LocalizationSource"); } if (_localizationSource == null || _localizationSource.Name != LocalizationSourceName) { _localizationSource = LocalizationManager.GetSource(LocalizationSourceName); } return _localizationSource; } } private ILocalizationSource _localizationSource; /// <summary> /// Constructor. /// </summary> protected ContentPageBase() { LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName; ObjectMapper = NullObjectMapper.Instance; LocalizationManager = NullLocalizationManager.Instance; } /// <summary> /// Gets localized string for given key name and current language. /// </summary> /// <param name="name">Key name</param> /// <returns>Localized string</returns> protected virtual string L(string name) { return LocalizationSource.GetString(name); } /// <summary> /// Gets localized string for given key name and current language with formatting strings. /// </summary> /// <param name="name">Key name</param> /// <param name="args">Format arguments</param> /// <returns>Localized string</returns> protected virtual string L(string name, params object[] args) { return LocalizationSource.GetString(name, args); } /// <summary> /// Gets localized string for given key name and specified culture information. /// </summary> /// <param name="name">Key name</param> /// <param name="culture">culture information</param> /// <returns>Localized string</returns> protected virtual string L(string name, CultureInfo culture) { return LocalizationSource.GetString(name, culture); } /// <summary> /// Gets localized string for given key name and current language with formatting strings. /// </summary> /// <param name="name">Key name</param> /// <param name="culture">culture information</param> /// <param name="args">Format arguments</param> /// <returns>Localized string</returns> protected virtual string L(string name, CultureInfo culture, params object[] args) { return LocalizationSource.GetString(name, culture, args); } }

同理,若我们使用了其他控件类时,可以增加一个Base类作为实例控件的基类的

比如Popup控件,就编写一个PopupBase基类。

在这里我们编写了两个基类

​编辑

本地化配置

新建一个TranslateExtension.cs作为Xaml标签的本地化处理类

[ContentProperty("Text")] public class TranslateExtension : DomainService, IMarkupExtension { public TranslateExtension() { LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName; } public string Text { get; set; } public object ProvideValue(IServiceProvider serviceProvider) { if (Text == null) return ""; var translation = L(Text); return translation; } }

在MauiBoilerplateLocalization.cs配置好SourceFiles

public static void Configure(ILocalizationConfiguration localizationConfiguration) { localizationConfiguration.Sources.Add( new DictionaryBasedLocalizationSource(MauiBoilerplateConsts.LocalizationSourceName, new XmlEmbeddedFileLocalizationDictionaryProvider( typeof(LocalizationConfigurer).GetAssembly(), "MauiBoilerplate.Core.Localization.SourceFiles" ) ) ); } 编写ViewModelBase

为实现Mvvm设计模式,页面需要绑定一个继承于ViewModelBase的类型

在ViewModelBase中,需要实现INotifyPropertyChanged以处理绑定成员变化时候的通知消息;

ViewModelBase集成于AbpServiceBase以方便ViewModel代码编写者使用常用的功能,比如字符串的本地化,配置,AutoMapper对象等。

如何将Abp框架融入.NET MAUI项目配置及基类编写步骤详解?

public abstract class ViewModelBase : AbpServiceBase, ISingletonDependency, INotifyPropertyChanged { public ViewModelBase() { LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName; } public event PropertyChangedEventHandler PropertyChanged; protected PropertyChangedEventHandler PropertyChangedHandler { get; } public void VerifyPropertyName(string propertyName) { Type type = GetType(); if (!string.IsNullOrEmpty(propertyName) && type.GetTypeInfo().GetDeclaredProperty(propertyName) == null) throw new ArgumentException("找不到属性", propertyName); } public virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler propertyChanged = PropertyChanged; if (propertyChanged == null) return; propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression) { if (PropertyChanged == null) return; string propertyName = GetPropertyName(propertyExpression); if (string.IsNullOrEmpty(propertyName)) return; RaisePropertyChanged(propertyName); } protected static string GetPropertyName<T>(Expression<Func<T>> propertyExpression) { if (propertyExpression == null) throw new ArgumentNullException(nameof(propertyExpression)); MemberExpression body = propertyExpression.Body as MemberExpression; if (body == null) throw new ArgumentException("参数不合法", nameof(propertyExpression)); PropertyInfo member = body.Member as PropertyInfo; if (member == null) throw new ArgumentException("找不到属性", nameof(propertyExpression)); return member.Name; } }

至此,我们完成了数据库的配置,内容页基类与ViewModel基类的编写,接下来可以制作我们的页面了。请看下一章将Abp移植进.NET MAUI项目(三):构建UI层 - 林晓lx - 自由互联 (cnblogs.com)

项目地址

jevonsflash/maui-abp-sample (github.com)