views:

113

answers:

5

I'm building a class project (seperate dll) that will contain various helper methods and common functionality, to be accessed by a range of different applications - an ASP.NET website, a web service and a Windows service.

Is there any way that this neutral class can determine the type of application that is calling it (so it could, for example, make a choice about how to log information)?

What other 'meta'-information is available to a class about what application is calling it?

+9  A: 

A class should have no knowledge about how it is being used. Remember it is a black box.

If you want to expose logging to a class, create a logging interface, that is passed to the class, in a constructor or a method.

Then each calling application can implement its own version of the logger, and the logging implementation can have the detail you are looking for. And the class will only use the interface for example to LogMessage, LogError, etc. . .

David Basarab
Exactly +1 :)
cwap
A: 

If you use a logging framework, such as NLog or Log4Net, the way you log things is configured in your client application. In your shared library, you'll just use a logger, without having to take care of the way log entries will be saved (files, event log, mail, etc.).

Romain Verdier
+5  A: 

You could get the information by looking at the stack trace:

StackTrace stackTrace = new StackTrace();            // Get call stack
StackFrame[] stackFrames = stackTrace.GetFrames();   // Get method calls (frames)
string methodName = stackFrames[0].GetMethod().Name; // Get method name
string type = stackFrames[0].GetType().ToString();   // Get the calling type

However, I think the better solution would be to use a more object-oriented approach. Create different loggers that implement the same interface. Pass an instance of your logger to the class depending on what is creating and using the class.

public interface ILogger 
{
    void Log(string message);
}

public class MyWorkerClass
{
    private ILogger m_Logger;

    public MyWorkerClass(ILogger logger)
    {
        m_Logger = logger;
    }

    public void Work()
    {
        m_Logger.Log("working")
    }

    // add other members...
}

public class MyService
{
    public void DoSomething()
    {
        ILogger logger = new MyServiceLogger();
        MyWorkerClass worker = new MyWorkerClass(logger);
        worker.Work();
    }
}
Kevin Babcock
Good to see someone answered the question that was asked
Matthew Whited
If he had asked how to shoot himself in the foot, should the question that was asked be answered?
John Saunders
Thank you! I will be revising my design to use the interfaces, but I like to know how to shoot myself in the foot anyway - could be useful in a more bizarre set of circumstances.
pete the pagan-gerbil
A: 

Although I completely agree with the answers here so far, you can get reflection information about the loaded modules, combining this with a stack trace, you can figure out the function and class that is calling your code and get the reflection info for that.

But, to reiterate, I agree with the other posts in that you should abstract this through an interface, as this makes it clear to other programmers how data will be used and reduces the chances of bugs being introduced due to a miss-understanding. (IMHO, reflection should really only be used for things like serialization and explicit operations directly controlled by attributes, such as the GUI editor in .Net)

Grant Peters
A: 

Your design. There is something wrong with it.

Factor out these "If its a X do it Y, if its an A do it B" choices by using dependency injection. Those behaviors that change in different contexts should be encapsulated into objects that implement a common interface. The caller will determine what implementation of an interface he wants you to use and injects it into your instance before calling your methods.

Will