Search code examples
entity-frameworkautofacgraphdiff

Resolving class that has extension methods with AutoFac


I am using a third party library GraphDiff which adds Extension methods to DBContext class. My Context class is inherited from Interface like following

 MyContext: DbContext,IMyContext 

IoC contained register MyContext as IMyContext. Interface doesn't have extension method's signature and third. Now i am not getting how MyContext will have that extension method? If i create Object of MyContext it has that method but when it gets Inject it doesn't


Solution

  • Extensions methods are not part of the type, it is a C# syntactic sugar. When you do :

    myContext.ExtensionMethod(); 
    

    the compiler will generate the following code :

    ExtensionContainer.ExtensionMethod(myContext); 
    

    Where ExtensionContainer is defined like this :

    public static class ExtensionContainer 
    {
        public static void ExtensionMethod(this DbContext context)
        { }
    }
    

    When you use an extension method, the compiler will call a static method. See Extension Methods (C# Programming Guide) for more information.

    You can't use the extension method in your case because context is no longer a DbContext but IMyContext and the extension methods are defined for DbContext not for IMyContext.

    If you want to use these extension methods, one possible solution is to add them to your interface.

    public interface IMyContext
    {
        T UpdateGraph<T>(T entity, Expression<Func<IUpdateConfiguration<T>, object>> mapping, UpdateParams updateParams = null) where T : class 
    
        // other methods / properties
    }
    

    And in your concrete context you will be allowed to use the extension method

    public class MyContext : DbContext, IMyContext
    {
        public T UpdateGraph<T>(T entity, Expression<Func<IUpdateConfiguration<T>, object>> mapping, UpdateParams updateParams = null) where T : class
        {
            DbContextExtensions.UpdateGraph<T>(this, entity, mapping, updateParams); 
        }
    }
    

    Another solution is not to rely anymore on IMyContext but injecting MyContext. This solution will make your application more difficult to test and will introduce a strong dependency with Entity Framework.

    By the way doing so may break Single Responsibility Principle but I don't see an easy way to solve this without big refactoring.