In my current .NET Core project, I want to inject two services into my controllers for dependency injection.
I wrote the following extension methods that each takes a IConfigurationSection
, sets up the corresponding ldapContext
and adds it to the services
collection:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
var authenticationLdapConfiguration = Configuration.GetSection("AuthenticationLdap");
services.ConfigureAuthenticationLdapServer(authenticationLdapConfiguration);
var shibAttribLdapConfiguration = Configuration.GetSection("ShibbolethAttributesLdap");
services.ConfigureShibbolethAttributeLdapServer(shibAttribLdapConfiguration);
}
}
public static class ServiceCollectionExtensions
{
public static void ConfigureAuthenticationLdapServer(this IServiceCollection services, IConfigurationSection authLdapConfiguration)
{
var ldapConnectionInfo = createLdapConnectionInfo(authLdapConfiguration);
IAuthenticationLdapContext ldapContext = new AuthenticationLdapContext(ldapConnectionInfo);
ldapContext.Bind();
services.AddSingleton<IAuthenticationLdapContext>(ldapContext);
}
public static void ConfigureShibbolethAttributeLdapServer(this IServiceCollection services, IConfigurationSection shibAttribsLdapConfiguration)
{
var ldapConnectionInfo = createLdapConnectionInfo(shibAttribsLdapConfiguration);
IShibbolethAttributeLdapContext ldapContext = new ShibbolethAttributeLdapContext(ldapConnectionInfo);
ldapContext.Bind();
services.AddSingleton<IShibbolethAttributeLdapContext>(ldapContext);
}
private static LdapConnectionInfo createLdapConnectionInfo(IConfigurationSection ldapServerConfiguration)
{
//set up connection info
}
}
public interface IShibbolethAttributeLdapContext : ILdapContext {}
public interface IAuthenticationLdapContext : ILdapContext {}
public interface ILdapContext
{
//signatures of the functionality implemented below
void Bind();
}
public class LdapContext : ILdapContext
{
public LdapContext(LdapConnectionInfo ldapConnectionInfo) { }
//lots of functionality that I ultimately need
public void Bind(){}
}
public class ShibbolethAttributeLdapContext : LdapContext, IShibbolethAttributeLdapContext
{
public ShibbolethAttributeLdapContext(LdapConnectionInfo ldapConnectionInfo) : base(ldapConnectionInfo) {}
}
public class AuthenticationLdapContext : LdapContext, IAuthenticationLdapContext
{
public AuthenticationLdapContext(LdapConnectionInfo ldapConnectionInfo) : base(ldapConnectionInfo) {}
}
I cannot change ILdapContext
nor LdapContext
as they are from an assembly that I don't manage.
Obviously, these methods only differ in the types that they wire up. Is there an elegant way to remove this duplication? My guess was to use generics or maybe a func, but I didn't come up with a solution.
UPDATE:
So I came up with this solution over the weekend that gets rid of the static extension methods as suggested by kayess:
public class Startup
{
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//set up services
var authLdapContext = createBoundLdapContext<AuthenticationLdapContext>(Configuration.GetSection("AuthServer"));
services.AddSingleton<IAuthenticationLdapContext>(authLdapContext);
var shibbAttribLdapContext = createBoundLdapContext<ShibbolethAttributeLdapContext>(Configuration.GetSection("ShibAttribServer"));
services.AddSingleton<IShibbolethAttributeLdapContext>(shibbAttribLdapContext);
}
private TContextInstance createBoundLdapContext<TContextInstance>(IConfigurationSection ldapServerConfiguration)
where TContextInstance : LdapContext
{
TContextInstance ldapContext = createLdapContext<TContextInstance>(ldapServerConfiguration);
ldapContext.Bind();
return ldapContext;
}
private TContextInstance createLdapContext<TContextInstance>(IConfigurationSection ldapServerConfiguration)
where TContextInstance : LdapContext
{
var ldapConnectioninfo = createLdapConnectionInfo(ldapServerConfiguration);
TContextInstance ldapContext = (TContextInstance)Activator.CreateInstance(typeof(TContextInstance), ldapConnectioninfo);
return ldapContext;
}
private LdapConnectionInfo createLdapConnectionInfo(IConfigurationSection ldapServerConfiguration)
{
var ldapConnectionInfo = new LdapConnectionInfo();
//set up ldapConnectionInfo
return ldapConnectionInfo;
}
}
Can I make it better?
ShibbolethAttributeLdapContext
? What isAuthenticationLdapContext
? How are we supposed to know what base types or interfaces these classes inherit from? – BCdotWEB Oct 21 '16 at 15:23module
(ninject lingo) of them and load them accordingly. – kayess Oct 21 '16 at 15:23services.ConfigureShibbolethAttributeLdapServer(ldapConnection)
, as such, they have to be static. msdn.microsoft.com/en-us/library/bb383977.aspx – Thaoden Oct 21 '16 at 15:32