勖日陽光 發表於 2024-6-30 11:18:00

无业游民写的最后一个.net有关项目框架

<p>理想很丰满,现实往往很残酷。</p>
<p>一种按照ddd的方式,根据业务来把自己需要的模块一个一个写出来,再按照模块把需要的接口一个一个的写出来,堆砌一些中间件,以及解耦的command,handler等等</p>
<p>,一个项目就这么成型了。上面的项目有一个非常清晰的特点,就是按需开发,不需要去可以定义业务相关的公共的模块,有就有没就没。这项目看起来没有什么公共框架,就是一个项目。当然这样效率性能也是最高的,不需要过多的包装一层又一层的公共代码。</p>
<p>有关示例如下,不做过多的赘述:</p>
<p>liuzhixin405/netcore-micro (github.com)</p>
<p>一种业务非常大,开发人员只需要写业务实现,这就需要一个公共框架,提供公共的可复制模块让业务人员写业务代码。</p>
<p>下面以为简洁的方式呈现这种开发模式,项目层级如下:</p>
<p><img src="https://img2024.cnblogs.com/blog/1099890/202406/1099890-20240630105609238-1424853453.png"></p>
<p>三个模块分别是业务模块,主机,基础模块。业务模块Business通过dll形式提供给host来完成注册和发布。</p>
<p>主机host可以存放公共的基础模块,例如注册、登录、认证等,这里省略。</p>
<p>业务模块存放业务代码,包括提供接口。</p>
<p>流程如下:request =&gt; 业务模块controller =&gt; business =&gt; service=&gt; repository</p>
<p>整个项目接口不变,实现可各异。</p>
<p><img src="https://img2024.cnblogs.com/blog/1099890/202406/1099890-20240630110348400-1620441811.png"></p>
<p>&nbsp;在仓储层定义几个公共的方法,</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span> IRepository&lt;TEntity,TID&gt; <span style="color: rgba(0, 0, 255, 1)">where</span> TEntity : IEntity&lt;TID&gt;<span style="color: rgba(0, 0, 0, 1)">
{
   Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> AddAsync(TEntity entity);
   Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> UpdateAsync(TEntity entity);

   Task</span>&lt;ApiResult&gt; DeleteAsync(Expression&lt;Func&lt;TEntity, <span style="color: rgba(0, 0, 255, 1)">bool</span>&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"> filter);
   Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> DeleteAsync(TID id);
   </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通用分页查询</span>
   Task&lt;PagedResult&lt;TEntity&gt;&gt; GetPagedAsync(PagingParameters&lt;TEntity&gt;<span style="color: rgba(0, 0, 0, 1)"> pagingParameters);

   </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 其他常用操作</span>
   Task&lt;IEnumerable&lt;TEntity&gt;&gt; FindAsync(Expression&lt;Func&lt;TEntity, <span style="color: rgba(0, 0, 255, 1)">bool</span>&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"> filter);

}</span></pre>
</div>
<p>服务层也是同样的方法</p>
<div class="cnblogs_code">
<pre>
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IService
{
    Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> AddAsync(IRequestDto requestDto);
    Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> UpdateAsync(IRequestDto requestDto);
    Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> DeleteAsyncc(IRequestDto requestDto);
    Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> GetPagedAsyncc(IRequestDto requestDto) ;
    Task</span>&lt;ApiResult&gt;<span style="color: rgba(0, 0, 0, 1)"> FindAsyncc(IRequestDto requestDto);
}</span></pre>
</div>
<p>&nbsp;</p>
<p>依赖注入还是老一套,实现它就行。</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IModule
{
   </span><span style="color: rgba(0, 0, 255, 1)">void</span> ConfigureService(IServiceCollection services, IConfiguration configuration = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
   </span><span style="color: rgba(0, 0, 255, 1)">void</span> Configure(IApplicationBuilder app, IWebHostEnvironment env = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ModuleBase : IModule
{
   </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ConfigureService(IServiceCollection services, IConfiguration configuration = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
   {
   }

   </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Configure(IApplicationBuilder app, IWebHostEnvironment env = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
   {
   }
}</span></pre>
</div>
<p>在主机通过扫描assembly来注册服务</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.AspNetCore.Mvc.ApplicationParts;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Reflect;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Reflection;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.ProjExtension;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Common;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.DependencyInjection;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Module;
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> Project.Host
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
    {
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> builder =<span style="color: rgba(0, 0, 0, 1)"> WebApplication.CreateBuilder(args);
            builder.Configuration.AddJsonFile(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">appsettings.json</span><span style="color: rgba(128, 0, 0, 1)">"</span>, optional: <span style="color: rgba(0, 0, 255, 1)">false</span>, reloadOnChange: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
            builder.Configuration.AddJsonFile($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">appsettings.{builder.Environment.EnvironmentName}.json</span><span style="color: rgba(128, 0, 0, 1)">"</span>, optional: <span style="color: rgba(0, 0, 255, 1)">true</span>, reloadOnChange: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
            builder.Configuration.AddJsonFile(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">appsettings.Modules.json</span><span style="color: rgba(128, 0, 0, 1)">"</span>, optional: <span style="color: rgba(0, 0, 255, 1)">false</span>, reloadOnChange: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">IModule注入 ,然后扫描调用ConfigureService,Business注入需要的服务入口</span>
<span style="color: rgba(0, 0, 0, 1)">            builder.Services.InitModule(builder.Configuration);
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> sp =<span style="color: rgba(0, 0, 0, 1)"> builder.Services.BuildServiceProvider();
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> moduleInitializers = sp.GetServices&lt;IModule&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> moduleInitializer <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> moduleInitializers)
            {
                moduleInitializer.ConfigureService(builder.Services, builder.Configuration);
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Add services to the container.</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> assemblys = GolbalConfiguration.Modules.Select(x =&gt;<span style="color: rgba(0, 0, 0, 1)"> x.Assembly).ToList();


            </span><span style="color: rgba(0, 0, 255, 1)">var</span> mvcBuilder=builder.Services.AddControllers().ConfigureApplicationPartManager(apm =&gt;<span style="color: rgba(0, 0, 0, 1)"> {

                </span><span style="color: rgba(0, 0, 255, 1)">var</span> folder = Path.Combine(Directory.GetCurrentDirectory(), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bus_lib</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> serviceList = (builder.Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ServiceList</span><span style="color: rgba(128, 0, 0, 1)">"</span>).Get&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>[]&gt;()) ?? <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">string</span>[] { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ADM</span><span style="color: rgba(128, 0, 0, 1)">"</span> };<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">默认加载基础服务</span>
                <span style="color: rgba(0, 0, 255, 1)">string</span>[] serviceFiles = Directory.GetFiles(folder, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*.Api.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span>).Where(x =&gt;<span style="color: rgba(0, 0, 0, 1)">
                  serviceList.Any(y </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> x.Contains(y))
                ).ToArray();

                </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> file <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> serviceFiles)
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (File.Exists(file))
                  {
                        </span><span style="color: rgba(0, 0, 255, 1)">var</span> assembly =<span style="color: rgba(0, 0, 0, 1)"> Assembly.LoadFrom(file);
                        </span><span style="color: rgba(0, 0, 255, 1)">var</span> controllerAssemblyPart = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> AssemblyPart(assembly);
                        apm.ApplicationParts.Add(controllerAssemblyPart);
                  }
                }
            });
            </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> assembly <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> assemblys)
            {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 扫描并注册其他程序集中的控制器</span>
<span style="color: rgba(0, 0, 0, 1)">                mvcBuilder.AddApplicationPart(assembly);
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 扫描并注册其他程序集中的服务   针对特性注入</span>
<span style="color: rgba(0, 0, 0, 1)">                builder.Services.ReisterServiceFromAssembly(assembly);
            }

            
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Learn more about configuring Swagger/OpenAPI at </span><span style="color: rgba(0, 128, 0, 1); text-decoration: underline">https://aka.ms/aspnetcore/swashbuckle</span>
<span style="color: rgba(0, 0, 0, 1)">            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();
            builder.Services.AddBusinessServices();

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> app =<span style="color: rgba(0, 0, 0, 1)"> builder.Build();
            ServiceLocator.Instance </span>=<span style="color: rgba(0, 0, 0, 1)"> app.Services;

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">imodule 的Configure调用,business可以实现中间件等操作</span>
            <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> moduleInitializer <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> moduleInitializers)
            {
                moduleInitializer.Configure(app, app.Environment);
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Configure the HTTP request pipeline.</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();

            app.UseAuthorization();


            app.MapControllers();

            app.Run();
      }
    }
}</span></pre>
</div>
<p>&nbsp;</p>
<p>业务需求注入代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ADM001_User.Model;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.AspNetCore.Builder;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.AspNetCore.Hosting;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.EntityFrameworkCore;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.Extensions.Configuration;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.Extensions.DependencyInjection;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> MongoDB.Bson.Serialization.Serializers;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> MongoDB.Bson.Serialization;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> MongoDB.Bson;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> MongoDB.Driver;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.IRepository;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Module;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Reflect;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Repository;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Services;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Collections;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Collections.Generic;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Linq;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Text;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Threading.Tasks;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ADM001_User.Business.Settings;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Model;

</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> ADM001_User.Business
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> UserModule : ModuleBase
    {

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ConfigureService(IServiceCollection services, IConfiguration configuration = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
      {
            services.AddDbContext</span>&lt;UserDbContext&gt;(options =&gt;<span style="color: rgba(0, 0, 0, 1)">
       options.UseInMemoryDatabase(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InMemoryDb</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">));

            services.AddScoped</span>&lt;IRepository&lt;User, <span style="color: rgba(0, 0, 255, 1)">int</span>&gt;, GenericRepository&lt;User, <span style="color: rgba(0, 0, 255, 1)">int</span>, UserDbContext&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">();
            services.AddTransient</span>&lt;IService, UserService&gt;<span style="color: rgba(0, 0, 0, 1)">();

            AddMongo(services);
            AddMongoRepository</span>&lt;User, <span style="color: rgba(0, 0, 255, 1)">int</span>&gt;(services, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">users</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

      }


      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> IServiceCollection AddMongo(IServiceCollection services)
      {
            BsonSerializer.RegisterSerializer(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> GuidSerializer(BsonType.String));
            BsonSerializer.RegisterSerializer(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> DateTimeOffsetSerializer(BsonType.String));
            services.AddSingleton(serviceProvider </span>=&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> configuration = serviceProvider.GetService&lt;IConfiguration&gt;<span style="color: rgba(0, 0, 0, 1)">();
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get&lt;ServiceSettings&gt;<span style="color: rgba(0, 0, 0, 1)">();
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> mongoDbSettings = configuration.GetSection(nameof(MongoDbSettings)).Get&lt;MongoDbSettings&gt;<span style="color: rgba(0, 0, 0, 1)">();
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> mongoClient = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MongoClient(mongoDbSettings.ConenctionString);
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> mongoClient.GetDatabase(serviceSettings.ServiceName);
            });
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> services;
      }
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> IServiceCollection AddMongoRepository&lt;T, TID&gt;(IServiceCollection services, <span style="color: rgba(0, 0, 255, 1)">string</span> collectionName) <span style="color: rgba(0, 0, 255, 1)">where</span> T : IEntity&lt;TID&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            services.AddSingleton</span>&lt;IRepository&lt;User, <span style="color: rgba(0, 0, 255, 1)">int</span>&gt;&gt;(serviceProvider =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> db = serviceProvider.GetService&lt;IMongoDatabase&gt;<span style="color: rgba(0, 0, 0, 1)">();
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> MongoRepository&lt;User, <span style="color: rgba(0, 0, 255, 1)">int</span>&gt;(db, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">collectionname</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> services;
      }
    }
}</span></pre>
</div>
<p>&nbsp;</p>
<p>在business层加了aop,通过proxy的方式</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Castle.DynamicProxy;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Microsoft.Extensions.DependencyInjection;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Collections.Generic;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Linq;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Reflection;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Runtime.CompilerServices;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Text;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Threading.Tasks;

</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Reflect
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ServiceExtension
    {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> ProxyGenerator _generator = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ProxyGenerator();
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> IServiceCollection AddBusinessServices(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)"> IServiceCollection services)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> folder = Path.Combine(Directory.GetCurrentDirectory(), <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bus_lib</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> dllFiles = Directory.GetFiles(folder, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*.Business.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> assemblies =<span style="color: rgba(0, 0, 0, 1)"> dllFiles.Select(Assembly.LoadFrom).ToArray();

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> businessTypes = assemblies.SelectMany(a =&gt; a.GetTypes().Where(t =&gt; t.IsClass&amp;&amp;!t.IsAbstract)).Where(type =&gt; type.GetInterfaces().Any(i =&gt; i.IsGenericType &amp;&amp; i.GetGenericTypeDefinition() == <span style="color: rgba(0, 0, 255, 1)">typeof</span>(IBusiness&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">))).ToList();
            CastleInterceptor castleInterceptor </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CastleInterceptor();

            </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> type <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> businessTypes)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> interfaceType = type.GetInterfaces().First(i =&gt; i.IsGenericType &amp;&amp; i.GetGenericTypeDefinition() == <span style="color: rgba(0, 0, 255, 1)">typeof</span>(IBusiness&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">));
                services.AddTransient(interfaceType, provider </span>=&gt;<span style="color: rgba(0, 0, 0, 1)">
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">var</span> target =<span style="color: rgba(0, 0, 0, 1)"> ActivatorUtilities.CreateInstance(provider, type);
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _generator.CreateInterfaceProxyWithTarget(interfaceType, target, castleInterceptor);
                });
            }

            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> services;
      }
    }
}</span></pre>
</div>
<p>在你需要的每个方法前加上特性就可以了</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.Model;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> Project.Base.ProjAttribute;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Collections.Generic;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Linq;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Text;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Threading.Tasks;

</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> ADM001_User.Business
{
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 有需要就实现前后动作
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AddAop: BaseAopAttribute
    {
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)"> Task After(BusinessAopContext aopContext)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
      }

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)"> Task Before(BusinessAopContext aopContext)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
      }
    }
}</span></pre>
</div>
<p>&nbsp;</p>
<p>再控制器层加了个公共的,不管是controller拦截还是公共的部分都可以写到这里</p>
<div class="cnblogs_code">
<pre> /</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)]

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> InitController&lt;TModel&gt;<span style="color: rgba(0, 0, 0, 1)">:ControllerBase
{
   </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> ILogger&lt;InitController&lt;TModel&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"> _logger;
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> InitController(ILogger&lt;InitController&lt;TModel&gt;&gt;<span style="color: rgba(0, 0, 0, 1)"> logger)
   {
         _logger </span>=<span style="color: rgba(0, 0, 0, 1)"> logger;

   }
   
}</span></pre>
</div>
<p>&nbsp;</p>
<p>该框架主打就是一个简陋,像日志,缓存 ,消息中间件都可以提前约定好公共接口,service层接口调用,business层注入需要的实现。按照接口和实现分离的方式该项目还需要调整下目录</p>
<p>地址如下:</p>
<p>liuzhixin405/single-arch (github.com)</p>

</div>
<div id="MySignature" role="contentinfo">
    <img loading="lazy" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_left_darkblue_121621.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1"><br><br>
来源:https://www.cnblogs.com/morec/p/18276172
頁: [1]
查看完整版本: 无业游民写的最后一个.net有关项目框架