4

I want to know, how the dependency injection is working in EFCore.

I want to change the behavior of the DbSetFinder to find not only the DbSet<> or DbQuery<> members, but finds the members which are inherited from it.

The current code is like this:

    private static DbSetProperty[] FindSets(Type contextType)
    {
        var factory = new ClrPropertySetterFactory();

        return contextType.GetRuntimeProperties()
            .Where(
                p => !p.IsStatic()
                     && !p.GetIndexParameters().Any()
                     && p.DeclaringType != typeof(DbContext)
                     && p.PropertyType.GetTypeInfo().IsGenericType
                     && (p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)
                         || p.PropertyType.GetGenericTypeDefinition() == typeof(DbQuery<>)))
            .OrderBy(p => p.Name)
            .Select(
                p => new DbSetProperty(
                    p.Name,
                    p.PropertyType.GetTypeInfo().GenericTypeArguments.Single(),
                    p.SetMethod == null ? null : factory.Create(p),
                    p.PropertyType.GetGenericTypeDefinition() == typeof(DbQuery<>)))
            .ToArray();
    }

This code is found the DbSet<> in the DbContext but does not found the members, which are inherited from DbSet<>. It means I have to extend the code with Type.IsAssignableFrom(Type) method, to find the inherited instances as well.

And I want to override in the default IDbSetFinder with my DbSetFinder class, the EFCore provide the functionality for it. Just I don't know where can I do this, and when can I do this.

There is a ServiceProvider, and possibility to change the implementation, But I don't know how to do it.

There is class where the core service dependencies are set:

    public virtual EntityFrameworkServicesBuilder TryAddCoreServices()
    {
        TryAdd<IDbSetFinder, DbSetFinder>();
        TryAdd<IDbSetInitializer, DbSetInitializer>();
        TryAdd<IDbSetSource, DbSetSource>();
        TryAdd<IDbQuerySource, DbSetSource>();
        ...

How Can I reach this service provider before it fills with default values, and how can I change the implementation of it.

1 Answer 1

6

The easiest (and probably intended public) way is to override OnConfiguring and use DbContextOptionsBuilder.ReplaceService method:

Replaces the internal Entity Framework implementation of a service contract with a different implementation.

e.g.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.ReplaceService<IDbSetFinder, CustomDbSetFinder>();
    // ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

How can I extract the IDbSetFinder from a given context?
@Shimmy As with any EF Core internal service, you'd need using Microsoft.EntityFrameworkCore.Infrastructure; to get access to AccessorExtensions, in particular GetService<T> extension method, which is the EF Core service locator, e.g.var dbSetFinder = dbContext.GetService<IDbSetFinder>();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.