I am using log4net, and want to simplify the usage. Right now, in every class I use logging (which is almost all all classes), I have to write:
public class MyClass
{
public static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
try
{
// do something
}
catch(Exception ex)
{
log.Error("Problem doing something", ex);
}
}
What I would really like to do is to put the first declaration in another class, which I could inherit wherever I need logging:
public class MyClass : Logging
{
try
{
// do something
}
catch(Exception ex)
{
log.Error("Problem doing something", ex);
}
}
public class Logging
{
public static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
But, if I do this, the problem is that
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
...ends up picking up the class name Logging, which is no good for the log. How do I get it to pick up the class name of the class where the inherited logging class is used?
Thanks!
If you inherit all your classes from Logging class then you won't be able to inherit classes from any other classes and create inheritance structure because C# does not support multiple inheritance. You really need to use composition not inheritance.
You can simplify calls to your logger by creating static helper class:
public static class LoggerHelper
{
public static void WriteError(string message,Exception ex, Type type)
{
var log = log4net.LogManager.GetLogger(type);
log.Error(message, ex);
}
}
And then in you classes you will call it like this:
public class MyClass
{
try
{
// do something
}
catch(Exception ex)
{
LoggerHelper.WriteError("Problem doing something", ex, this.GetType());
}
}
Declare your base class like so:
public abstract class Logging
{
public readonly log4net.ILog log = log4net.LogManager.GetLogger(this.GetType());
}
this.GetType() will always return the concrete type.
So you're gonna make all your classes inherit from Logging?
Inheritance is not meant for code reuse, it's meant to represent a "is a kind of" relationship between two domain entities. Don't abuse it.
What you need is composition.
public class MyClass
{
private static readonly ILog log = LogManager.GetLogger(typeof(MyClass));
}
MyClass has a logger, it is not a logger.
Related
I'm trying to write a logging class that would work like this:
Log.Info("Something happened");
Log.Error("Something else happened");
Log.Debug("Yet another thing happened!");
It should be accessible from every part of the namespace and quick to write, so I thought it'd be best to make it static. That way one can avoid having to create an object just to log a message.
At this point it is sort of like Console.WriteLine();
However, I wanted it also to be able to have two different modes: LogToConsole and LogToFile.
Thus the following syntax would be the most convenient:
LogConsole.Info("This will display in the console");
LogFile.Debug("This will be saved to a file");
LogAll.Error("This will be saved to a file AND displayed in a console");
However, I realized that there could be an large amount of "modes" multiplied by a very large amount of "logtypes".
How could I do this efficiently, in a way that I only have to write each logtype method once and depending on the derived class that calls the method, action a happens or action b happens?
Ideally I would like to define all methods once, and then create the classes that inherit them. But, since they are static methods their behavior is always the same. I can't tell them: "Find out what your superclass is and execute that class' SaveLog() method".
I realize that this would all be very very easy with abstract classes, but then I'd have to create objects.
Is there any way I could do this in C#?
Thanks!
Like Boo, would also recommend a logger like log4net.
If you do want to write it yourself, I would recommend against static methods as they would inhibit your ability to test the classes / methods that call it. Instead, inject your ILogger interface to all classes that might need logging. Then separate the "mode" from the target, so you can inject a list of targets to your logger.
public interface ILogTarget
{
void Save(string message);
}
public class LogToFile : ILogTarget
{
public void Save(string message)
{
//
}
}
public class LogToConsole : ILogTarget
{
public void Save(string message)
{
//
}
}
public interface ILogger
{
void Debug(string message);
}
public class Logger : ILogger
{
private readonly List<ILogTarget> _targets;
private static Logger _logger;
public Logger(List<ILogTarget> targets)
{
_targets = targets;
}
public void Debug(string message)
{
foreach (var target in _targets)
target.Save($"Debug: {message}");
}
}
public class TheClassThatMakesTheCall
{
private readonly ILogger _logger;
public TheClassThatMakesTheCall(ILogger logger)
{
_logger = logger;
}
public void AMethod()
{
_logger.Debug("some message");
}
}
//In your IoC, register Logger as a type of ILogger, and pass in the targets that you want
//If your target vary per situation, you'll need a ILogTarget factory that returns a different list of loggers based on the situation
You cannot inherit from static classes. But you can get away with making only the functions static. don't make the classes as static. Just make the functions as static, then you can use the "new" keyword in the derived class. It would be something like this
// IF this is your base class
public class Log
{
public static bool Info(string Message)
{
Console.WriteLine(Message + " From Log");
return true;
}
public static bool Success(string Message)
{
return true;
}
public static bool Error(string Message)
{
return true;
}
}
//Then this can be your derived class
public class LogFile : Log
{
public static new bool Info(string Message)
{
Console.WriteLine(Message + " From LogFile");
return true;
}
public static new bool Success(string Message)
{
return true;
}
public static new bool Error(string Message)
{
return true;
}
}
Hope this helps.
I have to use these two different class files across my application. How do I inherit those two class files in another class file?
This class file to writes an information log
Public class Log
{
Public void createLog()
{
}
}
This class file gets connection string
public class DataConnector
{
public void Connection()
{
}
}
I want to Inherit from those two classes in this class:
Public class FileOperation
{
public void FileWiter
{
}
}
Are there any different ways to access the class files across my project?
What I have tried:
Public class FileOperation
{
Log oLog=new Log();
DataConnector oDataconn=new DataConnector();
public void FileWiter
{
oLog.createLog();
}
}
Yes, I can use that method, but I'm looking for any other best ways to do this?
Basically, there is nothing wrong with your approach. There is even an OOP Design Principle called composition over inheritance, which calls for this way of doing it.
Think about DataConnector, does you FileWriter really specialize some kind of DataConnector?
What I would recommend though would be hiding your dependencies behind interfaces and injecting them via the constructor of FileOperation like so:
public class FileOperation
{
ILog log;
IDataConnector dataConnector;
public FileOperation(ILog log, IDataConnector dataConnector)
{
this.log = log;
this.dataConnector = dataConncetor;
}
public void FileWiter
{
this.log.createLog();
}
}
This way you could easily swap one or both of those dependecies by simply passing another object which implements the right interface. For example, you could create a MongoDbDataConnector which implements IDataConnector and pass this one instead of a MsSqlDataConnector or a PostgreSqlDataConnector.
There is no reason why your FileOperation should inherit from either Log nor DataConnector. Your FileOperation uses the Log and the DataConnector, but it shouldn't change how you Log or how you connect to your Data.
You could however prepare for the future, and create an interface for your Log class and for your DataConnector, so that at any time in the future you could easily swap those classes for another implementation, like so:
public interface ILogger
{
void Log(string message);
}
public interface IDataConnector<T>
{
IList<T> ReadList(Predicate<T> matches);
T ReadItem(Predicate<T> match);
}
and implement your classes for these interface.
In your FileOperation class, you can then set these over interfaces, and potentially later fill them using dependency injection, like so:
public class FileOperation
{
public ILogger Log { get; set; }
public IDataConnector DataConnector { get; set; }
public FileOperation()
: this(new Logger(), new DataConnector<string>())
{
}
public FileOperation(ILogger log, IDataConnector dataConnector) {
Log = log;
DataConnector = dataConnector;
}
}
I am planning to solve a particular problem by using abstract factory pattern. I was successful in implementing factory pattern but not able to extend factory pattern to Abstract factory
I have two different places where exception details can be stored
File system
Database
I have used factory pattern to abstract away object creation details from client
Interface
public interface ILogException
{
void LogException();
}
FileSystemLogger
public class FileExceptionLogger : ILogException
{
public void LogException()
{
Console.WriteLine("File Exception Logger");
}
}
DBSystemLogger
public class DBExceptionLogger : ILogException
{
public void LogException()
{
Console.WriteLine("DB Exception Logger");
}
}
Factory Implementation
public class ExceptionFactory
{
const int i = 1;
public static ILogException GetFactory()
{
if (i == 1)
{
return new FileExceptionLogger();
}
else if (i == 2)
{
return new DBExceptionLogger();
}
else
{
return new ServiceExcetionLogger();
}
}
}
I know this is not the best of implementation but i plan to change it.
Now FileSystemLogger and DatabaseLogger are in itself a factory, I want to group following implementation under FileSystemLogger and DatabaseLogger so that the client can have FileSystemLoggerFactory and DatabaseLoggerFactory
FileSystemLogger
FlatFileSystemLogger
XMLFileSystemLogger
DatabaseLogger
SQLSERVERLogger
OracleLogger
How should i proceed with defining FileSystemLoggerFactory and DatabaseLoggerFactory?
If you want, you could make the factory method a generic one:
public static ILogException GetFactory<T>() where T : ILogException
{
return (ILogException)Activator.CreateInstance<T>();
}
Call it like:
ILogException logger = ExceptionFactory.GetFactory<FileExceptionLogger>();
You also might want to take a look at a dependency injection library like NInject, Unity, etc. These can simplify this kind of problem, allowing you to centralize the logic for which interfaces get bound to which implementations. (Ie, you can bind an implementation in the application or request scope.)
class LogUtil<T> : ILogUtility
{
log4net.ILog log;
public LogUtil()
{
log = log4net.LogManager.GetLogger(typeof(T).FullName);
}
public void Log(LogType logtype, string message)
{
Console.WriteLine("logging coming from class {0} - message {1} " , typeof(T).FullName, message);
}
}
public class Logger
{
ILogUtility _logutility;
public Logger(ILogUtility logutility)
{
_logutility = logutility;
}
public void Log(LogType logtype, string message)
{
_logutility.Log(logtype, message);
}
}
I need to have the functionality to be flexible and have the ability to remove the LogUtil class in the future and use some thing else.
So I write LoggerUtility wrapper class as follows:
class LoggerUtility<T>
{
Logger logger;
public LoggerUtility()
{
LogUtil<T> logutil = new LogUtil<T>();
logger = new Logger(logutil);
}
public void Log(LogType logtype, string message)
{
logger.Log(logtype, message);
}
}
My client code as follows:
public class TestCode
{
public void test()
{
new LoggerUtility<TestCode>().Log(LogType.Info, "hello world");
}
}
To get loose coupling from LogUtil, I end up writing 2 wrapper classes Logger and LoggerUtility. So in the future, if I have to add another method
in the ILogUtility, I would have to add that method to Logger class and then LoggerUtility.
What is the best way to write LoggerUtility so that I could write the client code as follows:
new LoggerUtility<TestCode>().Log(LogType.Info, "hello world");
Please let me know.
Thanks
It looks like you're adding a level of abstraction where there really doesn't need to be one.
If we start with your end result, LoggerUtility just needs to have an interface that it can use to log things based on the LogType parameter.
Your Logger class, as its currently written, is just a thin wrapper around the ILogUtility interface. So why bother adding that layer? Why can't the Logger class use an ILogUtility instance directly? You could even go one step further and define your interface as ILogUtility<T> and know that when you create a LoggerUtility<Foo> that the instance of the logger it will use will be based on the Foo class.
But honestly, I think you may just be reinventing the wheel here. Take a look at Common Logging for .NET. It will probably ease what you're trying to do and make more sense in the long run.
You don't need a second wrapper, you need either a factory or to use a dependency injection framework to construct an appropriate wrapper around log4net.
Using Ninject, and modifying your interface, you can do
kernel.Bind(typeof(ILogUtility<>)).To(typeof(Log4NetUtil<>);
and instantiate it as
var logger = kernel.Get<ILogUtility<MyClass>>();
where the logger interface/class are:
public interface ILogUtility<T> where T : class
{
void Log(LogType logtype, string message);
}
public class Log4NetUtil<T> : ILogUtility<T> where T : class
{
log4net.ILog log;
public LogUtil()
{
log = log4net.LogManager.GetLogger(typeof(T).FullName);
}
public void Log(LogType logtype, string message)
{
Console.WriteLine("logging coming from class {0} - message {1} " , typeof(T).FullName, message);
}
}
I have an interface based class that I want to have a few static classes as properties. However, I can't seem to find a way to use a static class as an instance property on a class based on an interface.
public interface IHttpHelp
{
ItemsManager {get;set;}
}
public static class ItemsManager
{
//static methods
}
public class HttpHelper
{
public ItemsManager { get { return ItemsManager;}
}
The above code won't work because of the "ItemsManager is used like a variable but it's a type error." Is there anyway to use a class this way?
For some insight into what I'm doing - I have a few static helper classes that access the httpruntime and current context. I currently use them directly, but wanted to move into a container class that will be used IoC. I could make them instance classes and forget about it, but I'm wondering f there's a way to this.
You can't use a static class like that, because by definition you can't create an instance of it, so you can't return it from a property. Make it a singleton instead:
public class ItemsManager
{
#region Singleton implementation
// Make constructor private to avoid instantiation from the outside
private ItemsManager()
{
}
// Create unique instance
private static readonly ItemsManager _instance = new ItemsManager();
// Expose unique instance
public static ItemsManager Instance
{
get { return _instance; }
}
#endregion
// instance methods
// ...
}
public class HttpHelper
{
public ItemsManager ItemsManager { get { return ItemsManager.Instance; } }
}
This is not supported by the language directly. You can either write a proxy class manually or use a library like the Duck Typing Project to emit a proxy class at runtime.
Both will have the same result: you will have a class that implements the interface, and proxies all calls to the static methods of the static class. Whether you want to write this yourself or use the duck typing library is up to you.
EDIT: Thomas' answer of using a singleton would be the way to go, if you have that option.
Static classes can't implement interfaces--it really wouldn't make much sense. An interface provides a standard API that all instances will support and you can swap instances and polymorphically access the methods through the standard interface. With a static class, all references to it are through the class anyways.
Typically in this situation you want a factory to support DI of an instance class that implements your helper.
public interface IHttpHelper
{ }
public class RealHttpHelper
{ ... }
public class FakeHttpHelper
{ ... }
public static class HttpHelper
{
public static IHttpHelper Instance
{
get
{
return whatever ? new RealHttpHelper() : new FakeHttpHelper();
}
}
}
...
HttpHelper.Instance.Context...
...