I've a Web API application. In the solution of the application, there are several projects.
And all the API's are in one single project. And there is one project for business layer.
We want to write one logging class containing all the relevant methods in the business layer project and we are going to use "Enterprise Library Logging Block".
What is the correct procedure to get the related configuration from the web.config in the class of the business layer project.
Thanks in advance.
If the configuration is contained in web.config and the business layer assembly executes in the same appdomain as the Web API application then the only thing you will need to do is bootstrap the blocks you are using (in this case it sounds like just logging).
You could do this at application startup (e.g. App_Start):
Logger.SetLogWriter(new LogWriterFactory().Create());
In this approach the Business Layer will use the static facade Logger.Write to write LogEntries.
A better approach would be to create a small wrapper around a LogWriter that will bootstrap the block and expose the LogWriter for use in the business layer (and anywhere that needs logging). This is a bit more friendly for dependency injection since it's easy to register in a container and can be passed in as a dependency.
public class Logger
{
private Lazy<LogWriter> logWriter = new Lazy<LogWriter>(() =>
{
LogWriterFactory factory = new LogWriterFactory();
return factory.Create();
});
public LogWriter LogWriter
{
get { return logWriter.Value; }
}
}
Since internally LogWriter is a singleton and you only want to bootstrap once you would probably make the custom Logger class a singleton. (If you don't care about having an instance you could make Logger entirely static.)
Related
Let's say a dev has created a library that exposes a class ScheduledAction
All this class does is execute a method at a specified interval.
So you would use this way:
var scheduledAction = new ScheduledAction(methodToCall, 10000);
scheduledAction.Start();
Every 10 seconds, the methodToCall is executed.
Now let's say dev of the library decided that ScheduledAction will catch and log exceptions thrown by methodToCall.
To do this it needs a logger. As this is a library, the dev doesn't want to force the use of any particular logging library and or implementation. This should be controlled and configured by the application consuming the library.
This is a very simple example to illustrate the point.
While researching on this, I noticed a common approach is to expose some sort of contract for logging (via an interface) and the consuming application has to supply an implementation, which is "injected" via some sort of initialization method that the library exposes.
However logging may not be the only dependency a library needs from a consuming application.
I'm struggling to find concrete examples/best practices for such situations, in particular when building an application that uses an IoC container, like an Asp.NET Core Web App.
All the services are added to the container at startup. I would then need to "initialize" the above mentioned library passing in implementations of the required services, requesting them explicitly, which is pretty much using the container like a service locator and more importantly the instances passed to the library cannot be swapped later (I'm thinking of cases where the IoC container creates object based on options/configuration which may change even at run-time).
You have a few options available:
Expose an ILogger interface on the same lib assembly/package, and a Logger class. Have the Logger class expose a static method to set the internal logger instance to some class that implements it.
Instead of setting up an implementation of ILogger, one could just assign an Action to be executed by the static Logger class.
The important is to have this behavior exposed through an interface, so the ScheduleAction class can be easily tested.
Then, on the ScheduleAction class, just check if the Logger has the actual logger set, and call it when an exception occurs.
My group of projects is as follows:
1) Shared Class Library
Models
Entity Framework Classes (DB Contexts etc)
2) Web API
Uses the models and entity framework classes in (1) to communicate with the database.
3) Console Application
Creates instances of Models in (1) and saves them to the database using the entity framework classes there.
My question is:
Should I be creating a single DI Container class that has a ConfigureServices method that is shared between both the Console Application and the Web API?
Or does it make more sense for each of these applications to be responsible for binding their own dependencies?
Thanks in advance!
Ioc registrations
It depends on the nature of applications but in general i would say you want to split it up and have it in either application. Things that are the same in both application don't need abstraction and ioc registration (don't make things abstract that are not needed to be abstract).
That said, you see microsft uses the extension method pattern to add multiple demendencies at once like: services.AddMvc() is an extentension method to add 20 or so ioc registrations. You could do the same in your shared library. and simply add services.AddSharedLibrary() in your startup classes:
public static class MyServiceExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCOllection services)
{
services.Add<Interface1,Implemenetation1>();
services.Add<Interface2,Implemenetation2>();
return services;
}
}
Startup base class
You can also make an (abstract) base class for the Startup Class. But this would mean that your Shared library now needs dependencies on the HttpBuilder/Kestrel nuget package. which would be weird if you where making a Servicebus queue listener for example.
A good reason to make a base class for Startup is: if you want all your startup projects to have the same way and order to build up the Appsettings and/or you want them to use the same Appsettings as configuration for IOptions. But in this case i would recommend making a separate shared library for this that is specifically aimed to provide the same StartupBase and configuration.
We use ninject as our DI solution. How do I create a self sustaining class library dll with its own internal IOC. Basically I have created a service that does something and I want to register the bindings in the dll and just hand it to other people. I don't want them to care about any binding in my dll.
In the dll:
public class FirstService : IFirstService
{
public FirstService(ISecondService secondService, IThirdService thirdService)
{
//Saves locally
}
//Does stuff with second and third services
}
What the end user does:
public class ThirdService : IThirdService
{
//Create the actual implementation of this
}
What I want inside the dll:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IFirstService>.To<FirstService>();
kernel.Bind<ISecondService>.To<SecondService>();
}
I don't think I want to use IKernel here though, due to possible memory leakage.
There are 4 basic design approaches to DLLs that are commonly in use:
An application layer.
A plug-in.
A library.
A framework.
It sounds like you have one of the last 2, but it is not possible to tell based on your question which prototype you are referring to.
For an application layer, you would typically compose the components inside of the application, in the composition root, as close to the point of entry of the main executable application as possible.
For a plugin, it would typically have its own internal composition root that is fired by some method or event of the application it is plugging into (based on that application's composition root). This is sometimes facilitated by modules in DI containers.
A library would typically not have any internal composition, but would provide an API (sometimes implemented as a fluent builder) that makes it easy for the client application to compose the pieces together. See this post for a couple of ideas about how to do that.
A framework would need to have 1 or more explicit extension points for the application to integrate into. Think of how MVC controllers work. There is an internal scanning implementation that by default can instantiate any object that implements a certain interface. There is also an abstract factory that can be used to inject dependencies if the default constructor is not available (in MVC, that is IControllerFactory). See this post for more information about how to make a DI friendly framework.
I'm using ServiceStack for some time and had a setup with some basic logging using ServiceStack.Logging package. It works well to log the exceptions that go up the call stack.
In some cases I may need to log an event further on the stack. My structure is something like this:
ServiceInterface - containing the services
ServiceModel - containing the DTOs
BLL - the logic layer (I need to log something here)
I have also a ServiceBase that setup the logging interface as following:
public abstract class MyServiceBase : Service
{
public ILog log = LogManager.GetLogger(typeof(MyServiceBase));
}
What is the best approach to log information inside this BLL layer?
Currently, I only see the option of passing the ILog instance to the BLL class and use it down there.
Is there any other option?
Thanks!
You should never need to pass along the ILog instance. The LogFactory takes care of this. When your web application is starting up you need to set the LogManager via the following command:
ServiceStack.Logging.LogManager.LogFactory = new Log4NetFactory();
Once its is setup LogManager will always resolve to the correct logger.
public ILog log = LogManager.GetLogger(typeof(MyServiceBase));
All you ever have to do is add the logging property to each class you want logging and ensure the code always runs after you set the LogFactory.
For other project/solutions:
You can add the ServiceStack.Logging project to anything that needs logging. It is a lightweight solution and decouples you from Log4Net. Making changing logging implementations trivial. If you use ServiceStack's logging then all your logging and the internal ServiceStack logging will log together.
I'm using Log4Net to handle logging in my WPF application.
Currently, the logger is configured with the rest of the front-end code. I have to pass a reference to the Service layer and the Repository layer if I want to be able to use the logger in these layers (I'll actually be using StructureMap for this). This means the back-end has a dependency on the front-end and I don't like that.
I'm wondering how best to handle this? Should I configure the logger in the Repository layer?
log4net LogManager.GetLogger(string name) will return an existing logger instance if it has already been created (e.g., in another layer), so there is no need to pass logger objects around.
You do need to be aware of multiple threads/processes trying to write to the same log file at the same time. You can use the log4net MinimalLock, or try this third party solution. Neither is ideal (the codeproject one is inefficient and still hits concurrency problems). I have ended up writing my own (which unfortunately is not publicly available).
Logging is a common cross-cutting concern that I have seen handled in several different ways. The simplest method is to create a static class that lives in a common assembly that is shared by all the layers.
However, since you are using StructureMap for your IoC, a better solution would be to configure StructureMap to inject your logger class (which might be configured as a singleton, depending on your needs) into each instance created. I personally prefer property injection for such cross-cutting concern classes, so that constructors don't get cluttered, but that's a matter of preference.