Reputation: 1333
In the LoggingFacility documentation (http://docs.castleproject.org/Windsor.Logging-Facility.ashx) the following is stated:
"Allow you to ask for an ILoggerFactory instance to provide logging support to classes that are not managed by Windsor"
but how do I actually ask for an ILoggerFactory instance, if my class is not managed by Windsor??
TIA
Søren
continued:
i'm pretty new to using Windsor (IoC), so when you say 'why would you not have the class manager by Windsor' I start to wonder if you're saying that all classes should be managed by Windsor...
I'm working on some legacy code and has to create a service interface on top of it... something like:
namespace RESTServer.WindsorTestService
{
[ServiceContract(Namespace = "urn: RESTServer_WindsorTestService:IMyServiceClass")]
public interface IMyServiceClass
{
ILogger Logger // Will be injected by Windsor
{ get; set; }
[OperationContract]
[WebGet(UriTemplate = "MyMethod")]
int MyServiceMethod();
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyServiceClass : IMyServiceClass
{
private ILogger _logger = NullLogger.Instance;
public ILogger Logger // Will be injected by Windsor
{
get { return _logger; }
set { _logger = value; }
}
public int MyServiceMethod()
{
// ... which will populate val1, val2, val3
var val1 = 1;
var val2 = 10;
var val3 = 100;
var myCalc = new myLegacyClass(val1, val2, val3);
return myCalc.DoCalculate(1000);
}
}
public class myLegacyClass
{
private int _val1;
private int _val2;
private int _val3;
private static readonly ILog _logger = LogManager.GetLogger(typeof(myLegacyClass));
public myLegacyClass(int val1, int val2, int val3)
{
_val1 = val1;
_val2 = val2;
_val3 = val3;
}
public int DoCalculate(int val4)
{
_logger.Info("Doing some calculation");
return _val1 + _val2 + _val3;
}
}
}
where the legacy code already uses log4net.... It works ok, but I was wondering if the myLegacyClass should be changed to somehow get the logger from Windsor... I'm just not sure what the best way would be.....
TIA Søren
Upvotes: 4
Views: 1596
Reputation: 1743
To answer the question, this is what I've done in the past:
var factory = ServiceLocator.Current.GetInstance<ILoggerFactory>
var logger = factory.Create(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
This will get you what you need, but then again, it's no better than referencing log4net directly in those instances.
When using IoC and dealing with legacy classes, it gets to be a pain sometimes.
Upvotes: 0
Reputation: 889
The question was asked "Why would you not have the class managed by Windsor". Not claiming to be an expert on DI/IOC, but my understanding is that your Domain classes e.g. Models would not normally be managed by a DI / IOC. However if one of your Domain Classes needed to do some logging then it would need the ILogger.
I had been asking the same question, and as both solutions were tagged with possible code smell, am wondering whether there is a cleaner solution.
Upvotes: 0
Reputation: 27374
container.Resolve<ILoggerFactory>()
and you manage the factory and grab loggers yourself. The question is though - why would you not have the class manager by Windsor?
Upvotes: 4
Reputation: 410
Surely the point of using the LoggingFacility is so that your logging requirements are met by Windsor's configuration and your component doesn't care what logger is in use (if any?!)
Jak Charloton has a good intro here
Which shows how to use optional property dependency injection to get a logger instance.
If you HAVE to get a handle on an ILogger from a component that isn't created via the Windsor container, then you COULD use a ServiceLocator (e.g. Microsoft.Practices.ServiceLocation) configured to talk to the Windsor container and get it that way.
i.e.
var logger = ServiceLocator.Current.GetInstance(typeof(ILogger)) as ILogger
ServiceLocator is rather a code smell tho' and should be avoided if possible - ditto using the Windsor container directly.
Upvotes: 1