迅速な開発のための4モジュラーエンド分離フレームワークの導入前と後のASP.NETコア、アイデアのモジュラー実現

ソース

GitHubの:https://github.com/iamoldli/NetModular

デモ住所

住所:http://129.211.40.240:6220
アカウント:管理者
パスワード:管理者

フロントエンドフレームワークデモ(仮)

住所:http://progqx5cu.bkt.clouddn.com/skins/index.html#/
アカウント:管理者
パスワード:管理者

ディレクトリ

1、開口部
2、すぐにサービスモジュールを作成するために
3は、データ・アクセス・モジュールが導入されました
アイデアの4、モジュラー実現を

公式のソースを入手します

見やすいソースコードについては、の次の公式のソースを取得してみましょう

ダウンロードAspNetCoreソース

git clone --recursive https://github.com/aspnet/AspNetCore

ダウンロードExtensionsソース

git clone https://github.com/aspnet/Extensions.git

ローディング機構ASP.NETコアコントローラ

参考資料:ASP.NETコアのアプリケーションメンバー

ASP.NET Core手段によってアプリケーションApplicationPartコントローラ、アセンブリのビュー等数字MVCヘルパー機能を発見するため、塗布部材が形成されているApplicationPartManager管理クラスに。お問い合わせの際AddMvcAddMvcCore方法がMVCに関連する機能を追加する際に、ASP.NET Core内部には、作成しApplicationPartManager、インスタンスをした後、出発点として、アセンブリへの入り口は、その依存ツリーのすべてのアセンブリ非公式のパッケージを見つけること、およびそのに追加ApplicationParts財産、そして最後にApplicationPartManager単一の実施の形態における容器への注入の例。ここでは、関連するソースコードは次のとおりです。

ソースパス:AspNetCore \ SRC \ Mvc.Core \ SRC \依存性の注入\ MvcCoreServiceCollectionExtensions.cs

public static IMvcCoreBuilder AddMvcCore(this IServiceCollection services)
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }

    var partManager = GetApplicationPartManager(services);
    //单例模式注入ApplicationPartManager
    services.TryAddSingleton(partManager);

    ConfigureDefaultFeatureProviders(partManager);
    ConfigureDefaultServices(services);
    AddMvcCoreServices(services);

    var builder = new MvcCoreBuilder(services, partManager);

    return builder;
}

//获取ApplicationPartManager实例
private static ApplicationPartManager GetApplicationPartManager(IServiceCollection services)
{
    var manager = GetServiceFromCollection<ApplicationPartManager>(services);
    if (manager == null)
    {
        manager = new ApplicationPartManager();

        var environment = GetServiceFromCollection<IHostingEnvironment>(services);
        var entryAssemblyName = environment?.ApplicationName;
        if (string.IsNullOrEmpty(entryAssemblyName))
        {
            return manager;
        }

       
        manager.PopulateDefaultParts(entryAssemblyName);
    }

    return manager;
}

ソースパス:AspNetCore \ SRC \ Mvc.Core \ SRC \ ApplicationParts \ ApplicationPartManager.cs

internal void PopulateDefaultParts(string entryAssemblyName)
{
    var entryAssembly = Assembly.Load(new AssemblyName(entryAssemblyName));
    var assembliesProvider = new ApplicationAssembliesProvider();

    //加载入口程序集的依赖项树中的所有非官方包的依赖程序集
    var applicationAssemblies = assembliesProvider.ResolveAssemblies(entryAssembly);

    foreach (var assembly in applicationAssemblies)
    {
        var partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly);
        foreach (var part in partFactory.GetApplicationParts(assembly))
        {
            ApplicationParts.Add(part);
        }
    }
}

私たちのすべてのモジュールがnugetパッケージによってインストールされているので、それは自動的に依存関係ツリーにコンパイルされ、我々は、手動でアセンブリモジュールをロードする必要はありません。

コンパイル時にアセンブリが参照されていないために、私たちは手動でアプリケーションによってメンバーをロードすることができます

// create an assembly part from a class's assembly
var assembly = typeof(Startup).GetTypeInfo().Assembly;
services.AddMvc()
    .AddApplicationPart(assembly);

// OR
var assembly = typeof(Startup).GetTypeInfo().Assembly;
var part = new AssemblyPart(assembly);
services.AddMvc()
    .ConfigureApplicationPartManager(apm => apm.ApplicationParts.Add(part));

ローディング機構モジュール

NetModularルールは、プロジェクトの開始時に、プログラムのルートディレクトリの下に見えるということであるmodulesディレクトリ、ディレクトリ情報は、すべてのモジュール専用に保存され、次のように、その構造は以下のとおりです。

Structureチャート

modulesそれぞれが各サブディレクトリ有するモジュールのサブディレクトリを表しmodule.json、次のような構造のモジュール情報を記述するために使用されるファイルを。

{"Id": "Admin","Name":"权限管理","Version":"1.0.0"}
  • 注意:module.jsonインストールモジュールがプロジェクトに含まれるNugetモジュールが自動的にコンパイルしながら、ファイルが自動的に生成され、袋にパッケージ化されています。これは、使用していますMSBuildのを、私たちは見ることができ興味を持っています。*

以下は、生成することでmodule.json、ファイルに対応する構成情報を

<Project>

  <PropertyGroup>
    <ModulesDir>modules\$(Id)</ModulesDir>
    <ModuleInfo>{"Id": "$(Id)","Name":"$(Name)","Version":"$(Version)"}</ModuleInfo>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="$(ModulesDir)\**">
      <Pack>true</Pack>
      <PackagePath>contentFiles\any\any\$(ModulesDir)</PackagePath>
      <PackageCopyToOutput>true</PackageCopyToOutput>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>Modules\$(Id)\%(RecursiveDir)%(FileName)%(Extension)</TargetPath>
    </Content>
  </ItemGroup>

  <Target Name="ModulesBuildBefore" AfterTargets="Build">

    <!--创建modules目录-->
    <MakeDir Directories="$(ModulesDir)"/>

    <!--生成module.json文件,Note:项目需要生成两次,否则Nuget包中的文件不是最新的-->
    <WriteLinesToFile File="$(ModulesDir)\module.json" Overwrite="true" Lines="$(ModuleInfo)" />
    
  </Target>

</Project>

NetModularなお、説明モジュール情報定義ModuleInfo.csクラス情報と記憶モジュールIModuleCollection.csインタフェースを

/// <summary>
/// 模块信息
/// </summary>
public class ModuleInfo
{
    /// <summary>
    /// 编号
    /// </summary>
    public string Id { get; set; }

    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 版本
    /// </summary>
    public string Version { get; set; }

    /// <summary>
    /// 模块初始化器
    /// </summary>
    public IModuleInitializer Initializer { get; set; }

    /// <summary>
    /// 程序集信息
    /// </summary>
    public ModuleAssembliesInfo AssembliesInfo { get; set; }
}

/// <summary>
/// 模块集合
/// </summary>
public interface IModuleCollection : IList<ModuleInfo>
{

}

IModuleCollectionクラスを実装したModuleCollection.csクラスのコンストラクタで行われるロードされたモジュールのリスト操作は次のとおりです。

public ModuleCollection()
{
    var moduleJsonFiles = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "modules"), "module.json", SearchOption.AllDirectories);

    foreach (var file in moduleJsonFiles)
    {
        var moduleInfo = JsonConvert.DeserializeObject<ModuleInfo>(File.ReadAllText(file));
        if (moduleInfo != null)
        {
            //判断是否已存在
            if (_moduleInfos.Any(m => m.Name.Equals(moduleInfo.Name)))
                continue;
            var assemblyHelper = new AssemblyHelper();
            //此处默认模块命名空间前缀与当前项目相同
            moduleInfo.AssembliesInfo = new ModuleAssembliesInfo
            {
                Domain = assemblyHelper.Load(m => m.Name.EndsWith("Module." + moduleInfo.Id + ".Domain")).FirstOrDefault(),
                Infrastructure = assemblyHelper.Load(m => m.Name.EndsWith("Module." + moduleInfo.Id + ".Infrastructure")).FirstOrDefault(),
                Application = assemblyHelper.Load(m => m.Name.EndsWith("Module." + moduleInfo.Id + ".Application")).FirstOrDefault(),
                Web = assemblyHelper.Load(m => m.Name.EndsWith("Module." + moduleInfo.Id + ".Web")).FirstOrDefault(),
            };

            Check.NotNull(moduleInfo.AssembliesInfo.Domain, moduleInfo.Id + "模块的Domain程序集未发现");
            Check.NotNull(moduleInfo.AssembliesInfo.Infrastructure, moduleInfo.Id + "模块的Infrastructure程序集未发现");
            Check.NotNull(moduleInfo.AssembliesInfo.Application, moduleInfo.Id + "模块的Application程序集未发现");
            Check.NotNull(moduleInfo.AssembliesInfo.Web, moduleInfo.Id + "模块的Web程序集未发现");

            //加载模块初始化器
            var moduleInitializerType = moduleInfo.AssembliesInfo.Web.GetTypes().FirstOrDefault(t => typeof(IModuleInitializer).IsAssignableFrom(t));
            if (moduleInitializerType != null && (moduleInitializerType != typeof(IModuleInitializer)))
            {
                moduleInfo.Initializer = (IModuleInitializer)Activator.CreateInstance(moduleInitializerType);
            }

            Add(moduleInfo);
        }
    }
}

プロジェクトを開始する場合、最初の作成ModuleCollectionモジュールは常に、システム内の情報にアクセスできるように、単一噴射モードの実施形態を使用して、コンストラクタ負荷で、すべてのモジュール情報をインスタンス。

/// <summary>
/// 添加模块
/// </summary>
/// <param name="services"></param>
/// <param name="env"></param>
/// <returns></returns>
public static IModuleCollection AddModules(this IServiceCollection services, IHostingEnvironment env)
{
    //创建模块集合对象
    var modules = new ModuleCollection();
    services.AddSingleton<IModuleCollection>(modules);

    var cfgHelper = new ConfigurationHelper();
    var cfg = cfgHelper.Load("module", env.EnvironmentName, true);

    //通用配置
    services.Configure<ModuleCommonOptions>(cfg);

    foreach (var module in modules)
    {
        if (module == null)
            continue;

        services.AddApplicationServices(module);

        if (module.Initializer != null)
        {
            module.Initializer.ConfigureServices(services);

            module.Initializer.ConfigOptions(services, cfg.GetSection(module.Id));

            services.AddSingleton(module);
        }
    }

    return modules;
}

そして、ミドルウェア依存性注入処理モジュール

どのような情報を見ては、モジュールに含まれています。

Structureチャート

モジュールは、2つのカテゴリに注入します:

1、合意

各モジュールは、構成アイテム(オプション)、エンティティ(エンティティ)、ストレージ(リポジトリ)、データベースコンテキスト(DbContext)、仕事(のUnitOfWork)のユニット、サービス(サービス)、彼らはネーミングを含めて、よく一致している、ディレクトリを持っています、利用状況など、ユーザーがのみを使用するためのルールに従う必要がありますので、ケアは、物事を注入する必要はありません、彼らは自動的に注入されたシステムです。

データ・アクセスの例では、ストレージアクセス関連データ(リポジトリ)、コンテキストデータベース(DbContext)、作業単位(UnitOfWorkの)は、構成情報及び注入モジュールに基づいて自動的に実行され、及びであるScoped方法注入。表示するには、特定のコードData.AspNetCoreのプロジェクトを。

2、カスタム

各モジュールは、独自のサービスを注入するためにいくつかの必要性であってもよいし、これらのサービスは、カスタムの一部を手動で注入するために、開発者が必要です。例えば、权限管理(Admin)モジュール权限验证处理(PermissionValidateHandler.cs)実装し、IPermissionValidateHandlerインタフェースは、権限の検証を行うために設計されています。

注射に加えて、各中間モジュールは、プロジェクトに沿ってこの情報を統合するために、いくつかの機能のためにユニークで特別な構成を有しているNetModular抽象1つのIModuleInitializer以下の4つのメソッドを含むインタフェース。

/// <summary>
/// 模块初始化器接口
/// </summary>
public interface IModuleInitializer
{
    /// <summary>
    /// 注入服务
    /// </summary>
    /// <param name="services"></param>
    void ConfigureServices(IServiceCollection services);

    /// <summary>
    /// 配置中间件
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    void Configure(IApplicationBuilder app, IHostingEnvironment env);

    /// <summary>
    /// 配置MVC
    /// </summary>
    /// <param name="mvcOptions"></param>
    void ConfigureMvc(MvcOptions mvcOptions);

    /// <summary>
    /// 配置选项
    /// </summary>
    /// <param name="services"></param>
    /// <param name="configuration"></param>
    void ConfigOptions(IServiceCollection services, IConfiguration configuration);
}

メソッド説明:

1、ConfigureServices:サービスを注入するための

2、設定:ミドルウェアを設定します

図3に示すように、ConfigureMvc:MVC関連機能を設定するために使用します

4、ConfigOptions:設定項目の設定モジュール

各モジュールでは、それが含まれている必要がありIModuleInitializer実現がModuleInitializerあり权限管理(Admin)、たとえば、モジュールを:

public class ModuleInitializer : IModuleInitializer
{
    public void ConfigureServices(IServiceCollection services)
    {
        //权限验证服务
        services.AddScoped<IPermissionValidateHandler, PermissionValidateHandler>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    }

    public void ConfigureMvc(MvcOptions mvcOptions)
    {
        // 审计日志过滤器
        mvcOptions.Filters.Add(typeof(AuditingFilter));
    }

    public void ConfigOptions(IServiceCollection services, IConfiguration configuration)
    {
        // Admin配置项
        services.Configure<AdminOptions>(configuration);
    }
}

システムが起動されると、それはステップで指定され、呼び出された場合など、これらのモジュールの対応するメソッドを呼び出すservice.AddModules方法の間に、モジュールが横断し、カスタムサービスと構成項目を注入します、

public static IModuleCollection AddModules(this IServiceCollection services, IHostingEnvironment env)
{
    var modules = new ModuleCollection();
    services.AddSingleton<IModuleCollection>(modules);

    var cfgHelper = new ConfigurationHelper();
    var cfg = cfgHelper.Load("module", env.EnvironmentName, true);

    services.Configure<ModuleCommonOptions>(cfg);

    // 遍历模块
    foreach (var module in modules)
    {
        if (module == null)
            continue;

        services.AddApplicationServices(module);

        // 判断IModuleInitializer实现是否存在
        if (module.Initializer != null)
        {
            // 注入服务
            module.Initializer.ConfigureServices(services);

            //配置配置项
            module.Initializer.ConfigOptions(services, cfg.GetSection(module.Id));

            services.AddSingleton(module);
        }
    }

    return modules;
}

この時点で、すべての情報モジュールがシステムに統合されている〜

オリジナルスターター:4を迅速に開発するための分離ASP.NETコアモジュラーフレームワークの終わりの前と後には、アイデアのモジュラー実現を紹介します

おすすめ

転載: www.cnblogs.com/oldli/p/10945137.html