Hi.
I'm thinking about fairly common problem -
service binding. I'd like to have access to
common services from all over the code without
any special attenction. The .NET's service provider
architecture achieves this, but has one drawback -
given service is configured once for whole system;
my analysis shows that i have to bind services,
depending on who is requesting. Below there are
four solutions, but none of them satisfies me.
All of them assume there is "wise" class
called ServiceManager which is able to resolve
references and handle the context tracking -
probably solution used in Log4Net (loggers
defined by name and assigned after caller
type name analysis) would be sufficient for
my purposes. The problem i'm trying to aim here
is the "client side" code. So - let's start with
Log4Net approach:
/* Idea 0 */
public class ServiceByDirectReferenceBinding
{
public void do()
{
LogService.GetLogService(this).Log("doing");
DaoService.GetDaoService(this).TestConnection();
}
}
#region Static service access wrappers...
public class LogService
{
static ILogService GetLogService(object caller)
{
return ServiceManager.Get(typeof(ILogService), caller)
}
}
public class DaoService
{
static IDaoService GetDaoService(object caller)
{
return ServiceManager.Get(typeof(IDaoService), caller)
}
}
//for real life sample - see Log4Net api...
//the static service access methods could have been
//avoided, but then client code would require
//direct service manager calls and type casts upon
//every service method call (what binds client
//code directly to service manager - and it would be
//good to avoid it...)
#endregion
/* Idea 1 */
public class ServiceByProperties
{
#region "This could have been generated"
private ILogService logger;
private ILogService Logger
{
get
{
if(logger!=null)
return logger;
logger=ServiceManager.Get(typeof(ILogService),this);
return logger;
}
}
private IDaoService dao;
private IDaoService Dao
{
get
{
if(dao!=null)
return dao;
dao=ServiceManager.Get(typeof(IDaoService),this);
return dao;
}
}
#endregion
public void do()
{
//and such "client" api is my target :)
Logger.Log("doing...");
Dao.TestConntection();
}
}
/* Idea 2 */
public class ServiceByInjection
{
private ILogService Logger;
private IDaoService Dao;
public ServiceByInjection()
{
ServiceManager.InjectDependencies(this);
//or ensure dependencies are injected
//by caller, what is easy for services resolved using
//service manager (dependencies injected during
//ServiceManager.Get()), but not possible for
//plain objects created with usual o=new O()
}
public void do()
{
Logger.Log("doing...");
Dao.TestConntection();
}
}
/* Idea 3 */
public class ServiceByMagic
{
public void do()
{
Logger.Log("doing...");
Dao.TestConntection();
}
}
#region This could have been generated
public static class Logger: implements statically interface ILogService
{
static void Log(string message)
{
ServiceManager.Get(typeof(ILogService),
FindOutWhoCalledMe()).Log(message);
}
...
}
public static class Dao: implements statically interface IDaoService
{
static bool TestConntection()
{
return ServiceManager.Get(typeof(IDaoService), FindOutWhoCalledMe());
}
...
}
#endregion
At the moment it seems Idea 3 would be really nice if
it's possible to generate wrapper classes
and implement FindOutWhoCalledMe() somehow...
Any ideas how to start? (reflection.emit?
compiler services?)
--
greetings
marcin