DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Migrate, Modernize and Build Java Web Apps on Azure: This live workshop will cover methods to enhance Java application development workflow.

Modern Digital Website Security: Prepare to face any form of malicious web activity and enable your sites to optimally serve your customers.

Kubernetes in the Enterprise: The latest expert insights on scaling, serverless, Kubernetes-powered AI, cluster security, FinOps, and more.

E-Commerce Development Essentials: Considering starting or working on an e-commerce business? Learn how to create a backend that scales.

Related

  • Architecting Scalable ASP.NET Core Web APIs With Abstract Factory Method and Onion Architecture
  • Implementing Cache Dependency in ASP.NET Core
  • Revolutionizing Content Management
  • Revolutionizing API Development: A Journey Through Clean Architecture With Adapter Pattern in ASP.NET Core

Trending

  • What Is SQL Vector Database?
  • Extend Your GPTs With C#
  • A Modern Open-Source Technology That Conquers ACH Batch Processing
  • Be a Better Team Player
  1. DZone
  2. Coding
  3. Frameworks
  4. A Generic Logger Factory Facade for Classic ASP.NET

A Generic Logger Factory Facade for Classic ASP.NET

A web developer discusses when creating logger system for a web application makes sense, and how to do so in an ASP.NET-based web application.

Juergen Gutsch user avatar by
Juergen Gutsch
·
Apr. 18, 18 · Tutorial
Like (2)
Save
Tweet
Share
7.6K Views

Join the DZone community and get the full member experience.

Join For Free

ASP.NET Core already has this feature. There is a ILoggerFactory to create a logger. You are able to inject the ILoggerFactory to your component (Controller, Service, etc.) and to create a named logger out of it. During testing you are able to replace this factory with a mock, to not test the logger as well, and to not have an additional dependency to setup.

Recently, we had the same requirement in a classic ASP.NET project, where we used Ninject to enable dependency injection and log4net to log all the stuff we did and all the exceptions. One important requirement was creating a named logger per component.

Creating Named Loggers

Usually log4net gets created inside the components as a private static instance:

private static readonly ILog _logger = LogManager.GetLogger(typeof(HomeController)); 

There already is a static factory method to create a named logger. Unfortunately, this isn't really testable anymore and we need a different solution.

We could create a bunch of named loggers in advance and register them to Ninject, which obviously is not the right solution. We need to have a more generic solution. We figured out two different solutions:

// would work well
public MyComponent(ILoggerFactory loggerFactory)
{
    _loggerA = loggerFactory.GetLogger(typeof(MyComponent));
    _loggerB = loggerFactory.GetLogger("MyComponent");
    _loggerC = loggerFactory.GetLogger<MyComponent>();
}
// even more elegant
public MyComponent(
    ILoggerFactory<MyComponent> loggerFactoryA
    ILoggerFactory<MyComponent> loggerFactoryB)
{
    _loggerA = loggerFactoryA.GetLogger();
    _loggerB = loggerFactoryB.GetLogger();
}

We decided to go with the second approach, which is a simpler solution. This needs a dependency injection container that supports open generics like Ninject, Autofac, and LightCore.

Implementing the LoggerFactory

Using Ninject the binding of open generics looks like this:

Bind(typeof(ILoggerFactory<>)).To(typeof(LoggerFactory<>)).InSingletonScope(); 

This binding creates an instance of LoggerFactory<T> using the requested generic argument. If I request an ILoggerFactory<HomeController>, Ninject creates an instance of LoggerFactory<HomeController>.

We register this as a singleton to reuse the ILog instances as we would do using the usual way to create the ILog instance in a private static variable.

The implementation of the LoggerFactory is pretty easy. We use the generic argument to create the log4net ILog instance:

public interface ILoggerFactory<T>
{
ILog GetLogger();
}

public class LoggerFactory<T> : ILoggerFactory<T>
{
    private ILog _logger;
    public ILog GetLogger()
    {
        if (_logger == null)
        {
            var type = typeof(T);
            _logger = LogManager.GetLogger(typeof(T));
        }
        return _logger;
    }
}

We need to ensure the logger is created before creating a new one. Because Ninject creates a new instance of the LoggerFactory per generic argument, the LoggerFactory don't need to care about the different loggers. It just stores a single specific logger.

Conclusion

Now we are able to create one or more named loggers per component.

What we cannot do using this approach is to create individually named loggers, using a specific string as a name. There is a type needed that gets passed as a generic argument. So every time we need an individual named logger we need to create a specific type. In our case, this is not a big problem.

If you don't like to create types just to create individually named loggers, feel free to implement a non-genericLoggerFactory and make a generic GetLogger method as well as a GetLogger method that accepts strings as logger names.

ASP.NET Factory (object-oriented programming) Dependency injection

Published at DZone with permission of Juergen Gutsch, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Architecting Scalable ASP.NET Core Web APIs With Abstract Factory Method and Onion Architecture
  • Implementing Cache Dependency in ASP.NET Core
  • Revolutionizing Content Management
  • Revolutionizing API Development: A Journey Through Clean Architecture With Adapter Pattern in ASP.NET Core

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: