I want to create a repository base class, every service should inherit from this BaseService.
This is my code:
public class BaseService<TEntity, TAddDto, TUpdateDto, TEntityDto> : IBaseService<TEntity, TAddDto, TUpdateDto, TEntityDto>
where TEntity : Entity<long>
where TAddDto : class
where TUpdateDto : class
where TEntityDto : class
{
private readonly IFreeSql<SqlServerFlag> _fsql;
public BaseService(IFreeSql<SqlServerFlag> fsql)
{
_fsql = fsql;
}
public virtual async Task<IResultOutput> AddAsync(TAddDto input)
{
var addEntity = input.Adapt<TEntity>();
await _fsql.Insert(addEntity).ExecuteAffrowsAsync();
return ResultOutput.Ok();
}
public virtual async Task<IResultOutput> UpdateAsync(TUpdateDto input)
{
var property = typeof(TUpdateDto).GetProperty("Id");
if (property == null)
{
throw new ArgumentException("Id is not exist");
}
var obj = property.GetValue(input);
await _fsql.Update<TEntity>(input)
.Where(LambdaHelper.GetPropertyNameExpression<TEntity>("Id", obj))
.ExecuteAffrowsAsync();
return ResultOutput.Ok();
}
public virtual async Task<IResultOutput> GetAsync(long id)
{
var dto = await _fsql.Select<TEntity>()
.Where(a => a.Id == id)
.FirstAsync<TEntityDto>();
return ResultOutput.Ok();
}
public virtual async Task<IResultOutput> FakeDeleteAsync(long id)
{
int rows = await _fsql.Update<TEntity>()
.Set(LambdaHelper.GetPropertyNameMemberExpression<TEntity>("IsDeleted", true), true)
.Where(a => a.Id == id)
.ExecuteAffrowsAsync();
return rows > 0 ? ResultOutput.Ok() : ResultOutput.NotOk();
}
public virtual async Task<IResultOutput> DeleteAsync(long id)
{
int rows = await _fsql.Delete<TEntity>()
.Where(a => a.Id == id)
.ExecuteAffrowsAsync();
return rows > 0 ? ResultOutput.Ok() : ResultOutput.NotOk();
}
}
}
This is the IBaseService interface:
public interface IBaseService<TEntity, TAddDto, TUpdateDto, TEntityDto>
where TEntity : Entity<long>
where TAddDto : class
where TUpdateDto : class
where TEntityDto : class
{
Task<IResultOutput> AddAsync(TAddDto input);
Task<IResultOutput> UpdateAsync(TUpdateDto input);
Task<IResultOutput> GetAsync(long id);
Task<IResultOutput> FakeDeleteAsync(long id);
Task<IResultOutput> DeleteAsync(long id);
}
I create an InternationalService that inherits from BaseService<,,,> like this:
public class InternationalService: BaseService<InternationalEntity, InternationalAddInput, InternationalUpdateInput, InternationalDto>, IInternationalService
{
public InternationalService(IFreeSql<SqlServerFlag> fsql):base(fsql)
{
}
}
The IInternationalService interface looks like this:
public interface IInternationalService: IBaseService<InternationalEntity, InternationalAddInput, InternationalUpdateInput, InternationalDto>
{
}
I inject the service in Program.cs:
// Inject Generic Service
builder.Services.AddScoped(typeof(IBaseService<,,,>), typeof(BaseService<,,,>));
// Inject the end name Service
var types = Assembly.Load("Xin.Service")
.GetExportedTypes()
.Where(a => a.Name.EndsWith("Service"));
foreach (var type in types)
{
var interfaces = type.GetInterfaces();
foreach (var baseType in interfaces)
{
builder.Services.AddScoped(baseType, type);
}
}
I want every service to inherit from BaseService, so I can ignore the basic add update delete...code, but I can't run the code.
Can you please help me? Thanks when I run the app, the app don't work, the error was
Application terminated unexpectedly
System.ArgumentException: Cannot instantiate implementation type 'Xin.Service.International.IInternationalService' for service type 'Xin.Service.Base.IBaseService`4[Xin.Model.System.InternationalEntity,Xin.Service.International.Dto.InternationalAddInput,Xin.Service.International.Dto.InternationalUpdateInput,Xin.Service.International.Dto.InternationalDto]'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.Populate()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory..ctor(ICollection`1 descriptors)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
at Xin.Admin.WebApi.Program.Main(String[] args) in E:\home\NetCore\code\Xin.Admin\Xin.Admin.WebApi\Program.cs:line 22
IInternationalServiceas implementation typetypesto something like.Where(a => a.Name.EndsWith("Service") && !a.IsInterface && !a.IsAbstract)so it will try to register only the types that are instantiable.