György Gulyás
György Gulyás

Reputation: 1588

Entity Framework Dependency Injection

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.

Upvotes: 4

Views: 1352

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205609

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>();
    // ...
}

Upvotes: 6

Related Questions