Dependency Injection and Third-Party APIs - Extension Methods Using PI or Wrapper w / CI

I am working on a C # project that sits on top of a third-party CMS. The team uses Injection Dependency to facilitate loose coupling between classes.

I need to "extend" the CMS apis with common functions that are used on several pages.
Interestingly, these common functions have several dependencies. In this case, is it more expedient to extend this functionality using static extension methods or by creating new interfaces?

Context

Say a third party has two interfaces IContentLoaderand IPageSecuritythat work with objects Page:

namespace 3rdParty.Api
{
    public class Page{}

    public interface IContentLoader{
        T LoadItem<T>(Guid id) where T : Page;
    }

    public interface IPageSecurity
    {
        bool CurrentUserCanReadPage(Page p);   
    }
}

And I want to write a general method, for example:

public IEnumerable<T> LoadAllChildPagesTheUserCanRead(Guid id) where T:Page
{
    //load page, recursively collect children, then
    //filter on permissions
}

( , )

Property Injection:

public static class IContentLoaderExtensions
{
   public static Injected<IPageSecurity> PageSecurity {get;set;}

   public static IEnumerable<T> LoadAllChildItems(
      this IContentLoader contentLoader, Guid id){}
}

, IContentLoader, . , , Property Injection , , , .

, Wrapper:

public class AdvancedContentLoader
{        
     public AdvancedContentLoader(IContentLoader c, IPageSecurity p){
       //save to backing fields
     }

     IEnumerable<T> LoadAllChildItems(Guid id){}  
}

, , . , AdvancedContentLoader IContentLoader, .

, , - Property Injection? , - , ?

+4
3

, . , .

public interface IContentLoaderWithPageSecurity : IContentLoader
{
    IEnumerable<T> LoadAllChildItems<T>(IContentLoader contentLoader, Guid id) { }
}

, , intellisense . .

AdvancedContentLoader IContextLoader , .

public class AdvancedContentLoader : IContentLoaderWithPageSecurity 
{
    private readonly IContentLoader _internalContentLoader;
    private IPageSecurity _pageSecurity;

    public AdvancedContentLoader(IContentLoader contentLoader, IPageSecurity pageSecurity)
    {
        _internalContentLoader = contentLoader;
        _pageSecurity = pageSecurity;
    }

    // Chain calls on the interface to internal content loader
    public T LoadItem<T>(Guid id) where T : Page
    {
        return _internalContentLoader.LoadItem<T>(id);
    }

    public IEnumerable<T> LoadAllChildItems<T>(IContentLoader contentLoader, Guid id)
    {
        // do whatever you need to do here
        yield break;
    }
}

, DI, IContentLoaderWithPageSecurity , .

intellisense, using.

, , IContentLoader, IContentLoaderWithPageSecurity .

, , , , - "" - ConditionalWeakTable, .

Wiktor Zychla, .

+3

. SRP, - , , .

 public class DecoratedContentLoader : IContentLoader
 {        
     IContentLoader c;
     IPageSecurity p;

     public DecoratedContentLoader(IContentLoader c, IPageSecurity p)
     {
         this.c = c;
         this.p = p;           
     }

     public T LoadItem<T>(Guid id) where T : Page
     {
         var page = c.LoadItem<T>( id );
         if ( p.CanUserReadPage( p ) )
            return p;
         // throw or return null
     }
 }

, , .

, , , IContentProvider , , .

 public class AdvancedContentLoader
 {    
     // no need for additionak parameters, works
     // with any loader, including the decorated one    
     public AdvancedContentLoader( IContentLoader c )
     {
        //save to backing fields
     }

     IEnumerable<T> LoadAllChildItems(Guid id){}  
  }     
+2

, , . , API. API , , IContentLoader, - , :

  • ( Guid),
  • ,
  • ( IPageSecurity).

Microsoft,

"" , .

, , , . , IPageSecurity , . , , ? , .

+1

All Articles