diff --git a/src/InterfaceForward.Api/Controllers/Interface/InterfaceReturnConfigService.cs b/src/InterfaceForward.Api/Controllers/Interface/InterfaceReturnConfigService.cs
new file mode 100644
index 0000000..eadd3cf
--- /dev/null
+++ b/src/InterfaceForward.Api/Controllers/Interface/InterfaceReturnConfigService.cs
@@ -0,0 +1,84 @@
+using System.ComponentModel.DataAnnotations;
+using Fake;
+using Fake.AspNetCore;
+using InterfaceForward.Domain.Aggregates.InterfaceAggregate;
+using Microsoft.AspNetCore.Mvc;
+
+namespace SJZY.InterfaceRelay.Application.Services.Interface;
+
+///
+/// 接口返回配置
+///
+[ApiExplorerSettings(GroupName = "接口服务")]
+public class InterfaceReturnConfigService : ApplicationService
+{
+ private readonly IInterfaceReturnConfigRepository _interfaceReturnConfigRepository;
+ private readonly IInterfaceRepository _interfaceRepository;
+
+ ///
+ ///
+ ///
+ public InterfaceReturnConfigService(
+ IInterfaceReturnConfigRepository interfaceReturnConfigRepository
+ , IInterfaceRepository interfaceRepository)
+ {
+ _interfaceRepository = interfaceRepository;
+ _interfaceReturnConfigRepository = interfaceReturnConfigRepository;
+ }
+
+ ///
+ /// 接口配置列表,配置类型传null则全查
+ ///
+ /// 接口ID
+ ///
+ [HttpGet("InterfaceReturnConfig/GetList")]
+ public async Task> GetList([Required] int interfaceId)
+ {
+ return await _interfaceReturnConfigRepository.GetListAsync(interfaceId);
+ }
+
+ ///
+ /// 更新或新增
+ ///
+ /// 入参
+ ///
+ [HttpPost("InterfaceReturnConfig/Save")]
+ public async Task SaveAsync(InterfaceReturnConfigInput input)
+ {
+ if (!await _interfaceRepository.IsAnyAsync(x => x.Id == input.InterfaceId))
+ {
+ throw new BusinessException(message: "接口不存在");
+ }
+
+ // 开启事务
+ using var ts = TransacationHelper.GetReadCommitted();
+
+ foreach (var item in input.Items)
+ {
+ var entity =
+ ObjectMapper
+ .Map(item);
+ entity.InterfaceId = input.InterfaceId;
+ entity.Value ??= "";
+ switch (item.OptionType)
+ {
+ case OptionType.无:
+ break;
+ case OptionType.新增:
+ await _interfaceReturnConfigRepository.InsertOrUpdateAsync(entity, default);
+ break;
+ case OptionType.删除:
+ await _interfaceReturnConfigRepository.DeleteConfigByIdAsync(entity.Id);
+ break;
+ case OptionType.修改:
+ await _interfaceReturnConfigRepository.UpdateAsync(entity, ignoreAllNullColumns:true);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ ts.Complete();
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/InterfaceForward.Api/Controllers/Interface/ServiceProviderInterfaceService.cs b/src/InterfaceForward.Api/Controllers/Interface/ServiceProviderInterfaceService.cs
new file mode 100644
index 0000000..cbcf9fa
--- /dev/null
+++ b/src/InterfaceForward.Api/Controllers/Interface/ServiceProviderInterfaceService.cs
@@ -0,0 +1,287 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics;
+using Newtonsoft.Json;
+using SJZY.Expand.ABP.Common.Enums;
+using SJZY.InterfaceRelay.Application.Dtos.Interface;
+using SJZY.InterfaceRelay.Application.Services.Parameter;
+using SJZY.InterfaceRelay.Repository.Interface.Entitys;
+using SJZY.InterfaceRelay.Repository.Interface.Services;
+using SJZY.InterfaceRelay.Repository.Interface.ValueObjects;
+using SJZY.InterfaceRelay.Repository.ServiceProvider.Entitys;
+
+namespace SJZY.InterfaceRelay.Application.Services.Interface;
+
+///
+/// 服务商接口
+///
+[ApiExplorerSettings(GroupName = "接口服务")]
+public class ServiceProviderInterfaceService : ApplicationService
+{
+ private ParameterService ParameterService => LazyServiceProvider.LazyGetRequiredService();
+
+ private FormParameterService FormParameterService =>
+ LazyServiceProvider.LazyGetRequiredService();
+
+ private IInterfaceRepository InterfaceRepository =>
+ LazyServiceProvider.LazyGetRequiredService();
+
+ private IBasicRepository ServiceProviderRepository =>
+ LazyServiceProvider.LazyGetRequiredService>();
+
+ private IBasicRepository InterfaceMapRepository =>
+ LazyServiceProvider.LazyGetRequiredService>();
+
+
+ ///
+ /// 服务商接口分页列表
+ ///
+ ///
+ ///
+ [HttpPost("Interface/ServiceProviderInterfacePaginatedList")]
+ public async Task>
+ ServiceProviderInterfacePaginatedListAsync(ServiceProviderInterfacePaginatedInputObjectValue input)
+ {
+ return await InterfaceRepository.GetServiceProviderInterfacePaginatedListAsync(input);
+ }
+
+ ///
+ /// 获取服务商接口下拉列表
+ ///
+ /// 服务商id
+ ///
+ [HttpGet("Interface/GetServiceProviderInterfaceDropdownList")]
+ public async Task> GetServiceProviderInterfaceDropdownListAsync(
+ [Required] int serviceProviderId)
+ {
+ var res = await InterfaceRepository.GetListAsync(x => x.ServiceProviderId == serviceProviderId,
+ x => new { x.Id, x.Code, x.Name });
+
+ return res.Select(x => new ServiceProviderInterfaceDropdownListItem
+ {
+ Id = x.Id,
+ Name = x.Name,
+ Code = x.Code
+ }).ToList();
+ }
+
+ ///
+ /// 获取服务商接口明细
+ ///
+ /// 服务商接口id
+ ///
+ [HttpGet("Interface/GetServiceProviderInterfaceById")]
+ public async Task GetServiceProviderInterfaceByIdAsync([Required] int id)
+ {
+ // 接口基本信息
+ var interfaceEntity = await InterfaceRepository.GetFirstAsync(x => x.Id == id && !x.IsUpStream);
+ if (interfaceEntity == null)
+ {
+ throw new BusinessException(message: "服务商接口不存在");
+ }
+
+ var res = ObjectMapper.Map(interfaceEntity);
+
+ // 构造参数
+ var paras = await InterfaceRepository.GetParameterListByIdAsync(id);
+ // 入参树形列表
+ res.InParameterList = paras.Where(x => x.IsInPara).ToList();
+ // 出参树形列表
+ res.OutParameterList = paras.Where(x => !x.IsInPara).ToList();
+
+ // 表单列表
+ res.FormParameterList = await FormParameterService.GetParameterListAsync(id);
+
+ return res;
+ }
+
+
+ ///
+ /// 保存服务商接口
+ ///
+ ///
+ /// 用OptionType来区分操作目的,1:新增,2:删除,3:修改
+ ///tips:新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("Interface/SaveServiceProviderInterface")]
+ public async Task SaveServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input)
+ {
+ var res = new IdBaseDto();
+
+ switch (input.OptionType)
+ {
+ case OptionType.新增:
+ res.Id = await CreateServiceProviderInterfaceAsync(input);
+ break;
+ case OptionType.修改:
+ res.Id = await UpdateServiceProviderInterfaceAsync(input);
+ break;
+ case OptionType.删除:
+ await BatchDeleteServiceProviderInterfaceByIdsAsync(new List { input.Id ?? 0 });
+ break;
+ default:
+ res.Id = res.Id;
+ break;
+ }
+
+ return res;
+ }
+
+
+ ///
+ /// 批量删除服务商接口
+ ///
+ /// 服务商接口id集合
+ ///
+ [HttpPost("Interface/BatchDeleteServiceProviderInterfaceByIds")]
+ public async Task BatchDeleteServiceProviderInterfaceByIdsAsync([FromBody] List ids)
+ {
+ using var tran = TransacationHelper.GetReadCommitted();
+
+ // 删除接口
+ await InterfaceRepository.SoftDeleteAsync(x => !x.IsUpStream && ids.Contains(x.Id));
+ // 删除接口映射
+ var mapIds = await InterfaceMapRepository.GetListAsync(x => ids.Contains(x.DownStreamId), x => x.Id);
+ if (mapIds.Count > 0)
+ {
+ await InterfaceMapRepository.SoftDeleteAsync(x => mapIds.Contains(x.Id));
+ }
+
+ tran.Complete();
+
+ return true;
+ }
+
+ internal async Task CreateServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input)
+ {
+ // 校验参数合法性
+ ParameterService.ValidateParameter(
+ JsonConvert.DeserializeObject>(
+ JsonConvert.SerializeObject(input.InParameterList)));
+ ParameterService.ValidateParameter(
+ JsonConvert.DeserializeObject>(
+ JsonConvert.SerializeObject(input.OutParameterList)));
+
+
+ /*
+ * 1.校验业务逻辑
+ * 接口名唯一性,接口简码唯一性,请求地址唯一性
+ * 2.清洗数据结构
+ * 参数合并,参数合法性,参数扁平化bfs
+ * 3.数据持久化
+ * 由于业务的观测粒度是保存行为(即取消不做任何数据保存),因此保持行为可以直接覆盖上次行为,注意事务
+ */
+
+ #region 校验业务逻辑
+
+ if (await InterfaceRepository.IsAnyAsync(x =>
+ !x.IsUpStream && x.Name.Equals(input.Name) && x.ServiceProviderId == input.ServiceProviderId))
+ {
+ throw new BusinessException(message: $"接口名:{input.Name} 已存在");
+ }
+
+ #endregion
+
+ var interfaceEntity = ObjectMapper.Map(input);
+
+ interfaceEntity.IsUpStream = false;
+
+ // 开启事务
+ using var ts = TransacationHelper.GetReadCommitted();
+
+ // step1、生成接口编码
+ interfaceEntity.Code = await GenerateServiceProviderInterfaceCode(input.ServiceProviderId);
+ // step2、持久化接口
+ var interfaceId = await InterfaceRepository.InsertReturnIdentityAsync(interfaceEntity);
+ // 接口代码生成时并发兜底方案
+ if (await InterfaceRepository.CountAsync(x => x.Code.Equals(interfaceEntity.Code)) > 1)
+ {
+ throw new BusinessException(message: "接口代码生成异常,请稍后重试");
+ }
+
+ // step3、持久化参数
+ await ParameterService.CreateParametersAsync(input.InParameterList, interfaceId, true);
+ await ParameterService.CreateParametersAsync(input.OutParameterList, interfaceId, false);
+
+ // step4、持久化表单参数
+ if (input.FormParameterList.Count > 0)
+ {
+ await FormParameterService.CreateParametersAsync(input.FormParameterList, interfaceId);
+ }
+
+ // 提交事务
+ ts.Complete();
+
+ return interfaceId;
+ }
+
+ private async Task GenerateServiceProviderInterfaceCode(int serviceProviderId)
+ {
+ // 系统生成,由服务商代码+3位数字组成(0-999按顺序生成)
+ // tips:唯一性
+ var entity = await ServiceProviderRepository.GetFirstAsync(x => x.Id == serviceProviderId);
+ if (entity == null) throw new BusinessException(message: "服务商不存在");
+
+ string res = entity.Code;
+
+ // tips:要考虑并发
+ var code = await InterfaceRepository.GetCurrentCodeBySpId(serviceProviderId);
+ int count = 0;
+ if (!string.IsNullOrEmpty(code)) count = int.Parse(code.Substring(code.Length - 3, 3));
+ res += (count + 1).ToString().PadLeft(3, '0');
+
+ return res;
+ }
+
+ private async Task UpdateServiceProviderInterfaceAsync(ServiceProviderInterfaceInput input)
+ {
+ #region 校验业务逻辑
+
+ if (!await InterfaceRepository.IsAnyAsync(x => x.Id == input.Id))
+ {
+ throw new BusinessException(message: "服务商接口不存在");
+ }
+
+ if (await InterfaceRepository.IsAnyAsync(x =>
+ x.Name.Equals(input.Name) && x.Id != input.Id && !x.IsUpStream &&
+ x.ServiceProviderId == input.ServiceProviderId))
+ {
+ throw new BusinessException(message: $"接口名:{input.Name} 已存在");
+ }
+
+ #endregion
+
+ Debug.Assert(input.Id != null, $"{input.Id} 不能为空");
+
+ var interfaceEntity = ObjectMapper.Map(input);
+
+ // 开启事务
+ using var ts = TransacationHelper.GetReadCommitted();
+
+ // step1、更新接口
+ await InterfaceRepository.UpdateAsync(interfaceEntity, x => new
+ {
+ x.Code,
+ x.IsUpStream,
+ x.ServiceProviderId,
+ x.CreateTime,
+ x.CreateUserId,
+ x.IsDeleted
+ });
+
+ // step2、维护参数(增删改)
+ await ParameterService.MaintainParametersAsync(input.InParameterList, (int)input.Id, true);
+
+ await ParameterService.MaintainParametersAsync(input.OutParameterList, (int)input.Id, false);
+
+ // step3、更新表单参数
+ await FormParameterService.MaintainParametersAsync(input.FormParameterList, interfaceEntity.Id);
+
+ // 提交事务
+ ts.Complete();
+
+ return (int)input.Id;
+ }
+}
\ No newline at end of file
diff --git a/src/InterfaceForward.Api/Controllers/Interface/SystemInterfaceService.cs b/src/InterfaceForward.Api/Controllers/Interface/SystemInterfaceService.cs
new file mode 100644
index 0000000..0143847
--- /dev/null
+++ b/src/InterfaceForward.Api/Controllers/Interface/SystemInterfaceService.cs
@@ -0,0 +1,279 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics;
+using Newtonsoft.Json;
+using SJZY.Expand.ABP.Common.Enums;
+using SJZY.Expand.ABP.Core;
+using SJZY.Expand.ABP.Core.PublicMethords;
+using SJZY.InterfaceRelay.Application.Dtos.Interface;
+using SJZY.InterfaceRelay.Application.Services.Parameter;
+using SJZY.InterfaceRelay.Repository.Interface.Entitys;
+using SJZY.InterfaceRelay.Repository.Interface.Services;
+using SJZY.InterfaceRelay.Repository.Interface.ValueObjects;
+
+namespace SJZY.InterfaceRelay.Application.Services.Interface;
+
+///
+/// 系统接口
+///
+[ApiExplorerSettings(GroupName = "接口服务")]
+public class SystemInterfaceService : ApplicationService
+{
+ #region ctor
+
+ private readonly ParameterService _parameterService;
+ private readonly IInterfaceRepository _interfaceRepository;
+ private readonly IBasicRepository _interfaceMapRepository;
+
+ ///
+ /// 系统接口下拉列表缓存key
+ ///
+ private const string SystemInterfaceDropdownCacheKey = "SystemInterfaceDropdownCacheKey";
+
+ ///
+ public SystemInterfaceService(
+ IInterfaceRepository interfaceRepository
+ , ParameterService parameterService
+ , IBasicRepository interfaceMapRepository)
+ {
+ _parameterService = parameterService;
+ _interfaceMapRepository = interfaceMapRepository;
+ _interfaceRepository = interfaceRepository;
+ }
+
+ #endregion
+
+ ///
+ /// 系统接口分页列表
+ ///
+ ///
+ ///
+ [HttpPost("Interface/SystemInterfacePaginatedList")]
+ public async Task>
+ SystemInterfacePaginatedListAsync(SystemInterfacePaginatedInputObjectValue input)
+ {
+ return await _interfaceRepository.GetSystemInterfacePaginatedListAsync(input);
+ }
+
+ ///
+ /// 获取系统接口明细
+ ///
+ /// 系统接口id
+ ///
+ [HttpGet("Interface/GetSystemInterfaceById")]
+ public async Task GetSystemInterfaceByIdAsync([Required] int id)
+ {
+ // 接口基本信息
+ var interfaceEntity = await _interfaceRepository.GetFirstAsync(x => x.Id == id && x.IsUpStream);
+ if (interfaceEntity == null)
+ {
+ throw new BusinessException(message: "系统接口不存在");
+ }
+
+ var res = ObjectMapper.Map(interfaceEntity);
+
+ // 构造参数
+ var paras = await _interfaceRepository.GetParameterListByIdAsync(id);
+ // 入参树形列表
+ res.InParameterList = paras.Where(x => x.IsInPara).ToList();
+ // 出参树形列表
+ res.OutParameterList = paras.Where(x => !x.IsInPara).ToList();
+
+ return res;
+ }
+
+ ///
+ /// 获取系统接口下拉列表
+ ///
+ ///
+ [HttpGet("Interface/GetSystemInterfaceDropdownList")]
+ public async Task> GetSystemInterfaceDropdownListAsync()
+ {
+ var res =
+ (await RedisHelper.Client.GetAsync(SystemInterfaceDropdownCacheKey))
+ .ToObject>();
+ if (res == null)
+ {
+ res = await _interfaceRepository.GetSystemInterfaceDropdownListAsync();
+ await RedisHelper.Client.SetAsync(SystemInterfaceDropdownCacheKey, res.ToJson(), 2 * 60 * 60);
+ }
+
+ return res;
+ }
+
+ ///
+ /// 保存系统接口
+ ///
+ ///
+ /// 用OptionType来区分操作目的,1:新增,2:删除,3:修改
+ ///注意!新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("Interface/SaveSystemInterface")]
+ public async Task SaveSystemInterfaceAsync(SystemInterfaceInput input)
+ {
+ var res = new IdBaseDto();
+
+ switch (input.OptionType)
+ {
+ case OptionType.新增:
+ res.Id = await CreateSystemInterfaceAsync(input);
+ break;
+ case OptionType.修改:
+ res.Id = await UpdateSystemInterfaceAsync(input);
+ break;
+ case OptionType.删除:
+ await BatchDeleteSystemInterfaceByIdsAsync(new List { input.Id ?? 0 });
+ break;
+ default:
+ res.Id = res.Id;
+ break;
+ }
+
+ // 干掉缓存
+ await RedisHelper.Client.DelAsync(SystemInterfaceDropdownCacheKey);
+ return res;
+ }
+
+ ///
+ /// 批量删除系统接口
+ ///
+ /// 系统接口id集合
+ ///
+ [HttpPost("Interface/BatchDeleteSystemInterfaceByIds")]
+ public async Task BatchDeleteSystemInterfaceByIdsAsync([FromBody] List ids)
+ {
+ using var tran = TransacationHelper.GetReadCommitted();
+
+ // 删除接口
+ await _interfaceRepository.SoftDeleteAsync(x => x.IsUpStream && ids.Contains(x.Id));
+ // 删除接口映射
+ var mapIds = await _interfaceMapRepository.GetListAsync(x => ids.Contains(x.UpStreamId), x => x.Id);
+ if (mapIds.Count > 0)
+ {
+ await _interfaceMapRepository.SoftDeleteAsync(x => mapIds.Contains(x.Id));
+ }
+ // 删缓存
+ await RedisHelper.Client.DelAsync(SystemInterfaceDropdownCacheKey);
+
+ tran.Complete();
+
+ return true;
+ }
+
+ #region private
+
+ ///
+ /// 更新系统接口
+ ///
+ ///
+ ///
+ private async Task UpdateSystemInterfaceAsync(SystemInterfaceInput input)
+ {
+ #region 校验业务逻辑
+
+ var entity = await _interfaceRepository.GetFirstAsync(x => x.Id == input.Id && x.IsUpStream);
+
+ if (entity == null)
+ {
+ throw new BusinessException(message: "系统接口不存在");
+ }
+
+ if (await _interfaceRepository.IsAnyAsync(x =>
+ x.Id != input.Id && x.IsUpStream && x.Name.Equals(input.Name)))
+ {
+ throw new BusinessException(message: $"接口名:{input.Name} 已存在");
+ }
+
+ if (await _interfaceRepository.IsAnyAsync(
+ x => x.Id != input.Id && x.IsUpStream && x.Code.Equals(input.Code)))
+ {
+ throw new BusinessException(message: "接口code已存在");
+ }
+
+ #endregion
+
+ Debug.Assert(input.Id != null, $"{input.Id} 不能为空");
+
+ var interfaceEntity = ObjectMapper.Map(input);
+
+ // 开启事务
+ using var ts = TransacationHelper.GetReadCommitted();
+
+ // step1、更新接口
+ await _interfaceRepository.UpdateAsync(interfaceEntity, x => new
+ {
+ x.IsUpStream,
+ x.ServiceProviderId,
+ x.CreateTime,
+ x.CreateUserId,
+ x.IsDeleted
+ });
+
+ // step2、维护参数(增删改)
+ await _parameterService.MaintainParametersAsync(input.InParameterList, (int)input.Id, true);
+
+ await _parameterService.MaintainParametersAsync(input.OutParameterList, (int)input.Id, false);
+
+ // 这里再做参数校验,回滚代价是不是有点大了。。
+
+ // 提交事务
+ ts.Complete();
+
+ return (int)input.Id;
+ }
+
+ private async Task CreateSystemInterfaceAsync(SystemInterfaceInput input)
+ {
+ // 校验参数合法性
+ _parameterService.ValidateParameter(
+ JsonConvert.DeserializeObject>(
+ JsonConvert.SerializeObject(input.InParameterList)));
+ _parameterService.ValidateParameter(
+ JsonConvert.DeserializeObject>(
+ JsonConvert.SerializeObject(input.OutParameterList)));
+
+ /*
+ * 1.校验业务逻辑
+ * 接口名唯一性,接口简码唯一性,请求地址唯一性
+ * 2.清洗数据结构
+ * 参数合并,参数合法性,参数扁平化bfs
+ * 3.数据持久化
+ * 由于业务的观测粒度是保存行为(即取消不做任何数据保存),因此保持行为可以直接覆盖上次行为,注意事务
+ */
+
+ #region 校验业务逻辑
+
+ if (await _interfaceRepository.IsAnyAsync(x => x.IsUpStream && x.Name.Equals(input.Name)))
+ {
+ throw new BusinessException(message: $"接口名:{input.Name} 已存在");
+ }
+
+ if (await _interfaceRepository.IsAnyAsync(x => x.IsUpStream && x.Code.Equals(input.Code)))
+ {
+ throw new BusinessException(message: "接口code已存在");
+ }
+
+ #endregion
+
+ var interfaceEntity = ObjectMapper.Map(input);
+ interfaceEntity.IsUpStream = true;
+
+ // 开启事务
+ using var ts = TransacationHelper.GetReadCommitted();
+ // step1、持久化接口
+ var interfaceId = await _interfaceRepository.InsertReturnIdentityAsync(interfaceEntity);
+
+ // step2、持久化参数
+ await _parameterService.CreateParametersAsync(input.InParameterList, interfaceId, true);
+ await _parameterService.CreateParametersAsync(input.OutParameterList, interfaceId, false);
+
+ // 提交事务
+ ts.Complete();
+
+ return interfaceId;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/src/InterfaceForward.Api/InterfaceForwardApiModule.cs b/src/InterfaceForward.Api/InterfaceForwardApiModule.cs
index b8cceb5..1d0ac03 100644
--- a/src/InterfaceForward.Api/InterfaceForwardApiModule.cs
+++ b/src/InterfaceForward.Api/InterfaceForwardApiModule.cs
@@ -1,5 +1,6 @@
using Fake.AspNetCore;
using Fake.Authorization;
+using Fake.Helpers;
using Fake.Modularity;
using InterfaceForward.Api.Contract;
using InterfaceForward.Api.Filters;
diff --git a/src/InterfaceForward.Domain/InterfaceForwardDomainModule.cs b/src/InterfaceForward.Domain/InterfaceForwardDomainModule.cs
index 5b3852b..e3842ce 100644
--- a/src/InterfaceForward.Domain/InterfaceForwardDomainModule.cs
+++ b/src/InterfaceForward.Domain/InterfaceForwardDomainModule.cs
@@ -1,8 +1,9 @@
using System;
+using Fake.Modularity;
namespace InterfaceForward.Domain
{
- public class InterfaceForwardDomainModule
+ public class InterfaceForwardDomainModule : FakeModule
{
}
}
\ No newline at end of file