Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject the generic type in IServiceProvide.GetService dynamically in .net core

Here is the scenario I met:

In the Controller I want to inject the Generic Repository function like following:

using (var scope = HttpContext.RequestServices.CreateScope())
            {
                switch (voteRecordDto.ContentType)
                {
                    case ContentType.Question_Asking:
                        voteRecordType = "QuestionVoteRecord";
                        break;
                    case ContentType.Question_Answer:
                        voteRecordType = "AnswerVoteRecord";
                        break;
                    case ContentType.Question_AnswerComment:
                        voteRecordType = "CommentVoteRecord";
                        break;
                    default:
                        result = OperationResponse.Error("There is no accept Type!");
                        break;
                }
                using (var repository = scope.ServiceProvider.GetService<IVoteRecordRepository<QuestionVoteRecord>>())
                {
                    //...
                }
            }

There have three entities QuestionVoteRecord,AnswerVoteRecord,CommentVoteRecord that all inherit from VoteRecord The IVoteRepository interface is like:

 public interface IVoteRecordRepository<T> : IDisposable
{
    T Single(Guid voterGuid, int contentId);

    Task<T> SingleAsync(Guid voterGuid, int contentId);

    Task<bool> Add(T voteRecord);
}

The VoteRepository function is like that

 public class VoteRecordRepository<T> : IVoteRecordRepository<T> where T : VoteRecord, IDisposable
{
    private readonly EFDbContext _efDbContext;
    private readonly IQueryable<T> _queryable;

    public VoteRecordRepository(EFDbContext efDbContext)
    {
        _efDbContext = efDbContext;
        _queryable = _efDbContext.Set<T>();
    }

    public async Task<bool> Add(T voteRecord)
    {
        _efDbContext.Add(voteRecord);

        return await _efDbContext.SaveChangesAsync() > 0;
    }

    public T Single(Guid voterGuid, int contentId)
    {
        return _queryable
            .FirstOrDefault(p => p.ContentId == contentId && p.VoterId == voterGuid);
    }

    public async Task<T> SingleAsync(Guid voterGuid, int contentId)
    {
        return await _queryable
            .FirstOrDefaultAsync(p => p.ContentId == contentId && p.VoterId == voterGuid);
    }

    public void Dispose()
    {
        _efDbContext.Dispose();
    }
}

What I wanted is that:

If the ContentType is Question_Asking I want to get the IVoteRecordRepository<QuestionVoteRecord> in the GetService from ServiceProvider.

And when ContentType is Question_Answer I want is IVoteRecordRepository<AnswerVoteRecord> in the GetService from ServiceProvider.

PS:I am for you apology if my question is unclear or make u confused, cause my native language is not English. I hope u can help to edit it.

like image 392
doublnt Avatar asked Oct 22 '25 04:10

doublnt


2 Answers

You are very close to the solution. In your switch operator save the type of desired repository to some variable and then use IServiceProvider.GetService(Type serviceType) call for this type:

Type voteRecordType = null;
using (var scope = HttpContext.RequestServices.CreateScope())
{
    switch (voteRecordDto.ContentType)
    {
        case ContentType.Question_Asking:
            voteRecordType = typeof(IVoteRecordRepository<QuestionVoteRecord>);
            break;
        case ContentType.Question_Answer:
            voteRecordType = typeof(IVoteRecordRepository <AnswerVoteRecord>);
            break;
        case ContentType.Question_AnswerComment:
            voteRecordType = typeof(IVoteRecordRepository<CommentVoteRecord>);
            break;
        default:
            result = OperationResponse.Error("There is no accept Type!");
            break;
    }

    if (voteRecordType != null)
    {
        using (var repository = (IDisposable)scope.ServiceProvider.GetService(voteRecordType))
        {
            //...
        }
    }
}
like image 184
CodeFuller Avatar answered Oct 23 '25 21:10

CodeFuller


You have to bring in Microsoft.Extensions.DependencyInjection namespace to gain access to the generic

GetService<T>();
like image 39
Sameer Awate Avatar answered Oct 23 '25 19:10

Sameer Awate



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!