0

Essentially, I want to be able to determine the namespace of the caller class inside my service. The service instantiation happens with the default ASP.NET Core DI. A further obstacle may arise because I want to determine the caller inside the constructor of the base class and not directly in the instantiated service.

I suspect I know the answer to my question, but if It can happen, it wouldn't be the crazier thing I've seen.

Edit

Sample code

// First caller
namespace Example.Assembly.One
{
    public class CallerOne
    {
        consctructor(Service service)

        void WhichCallerAmI() { return this.service.ReturnCaller() }
        ...
    }   
}

// Second caller
namespace Example.Assembly.Two
{
    public class CallerTwo
    {
        consctructor(Service service)

        void WhichCallerAmI() { return this.service.ReturnCaller() }
        ...
    }   
}


// Service
namespace Example.Service
{
    public class Service : BaseService
    {
        consctructor() : base()

        public void ReturnCaller()
        {
            if (this.namespace == "Example.Assembly.One")
            {
                return "First caller";
            }

            return "Second caller";
        }  
    }   
}

// Base service
namespace Example.Service
{
    public class BaseService
    {
        consctructor(Service service)
        {
            // Determine namespace of caller here
            this.namespace = <insert-answer-here>
        }
    }   
}

// demo
// These callers can be controllers or other services
var firstCaller = new CallerOne() 
var secondCaller = new CallerTwo();

// firstResult now contains "First Caller"
var firstResult = firstCaller.WhichCallerAmI();

// secondResult now contains "Second Caller";
var secondResult = secondCaller.WhichCallerAmI();

XY problem

The Callers from the example represent data services in separete micro-service web projects, each using separate database. The problem I am trying to work around is to reuse the same service code for one entity, duplicated in all or some of the separate databases. My idea is to inject the relevant DbContext based on the namespace of the caller class, since we follow strict naming conventions either way.

Alex
  • 715
  • 1
  • 8
  • 29
  • 2
    This might be an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) that clarifies your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. – Nkosi Oct 07 '19 at 14:45
  • 1
    Why do you care about this? This *reverses* dependency injection. What is the real problem you want to solve? The easy way to do this at runtime would be to use eg [StackTrace](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.stacktrace?view=netcore-3.0) to find the calling method but why do that? If the caller's type matters, why not pass it as a generic type parameter? – Panagiotis Kanavos Oct 07 '19 at 14:57

1 Answers1

2

So you have a class:

public class Consumer
{
    public Consumer(Provider provider)
    {
        // ...
    }
}

And this class has the following dependency:

public class Provider : BaseProvider
{
    public Provider()
        : base()
    {
        // ...
    }
}

And this dependency has a base class:

public class BaseProvider
{
    public BaseProvider()
    {
        // ...
    }
}

And now in the constructor of BaseProvider you want to know for which caller it is being initialized?

You can't.

The dependency injection framework will be initializing the Provider service before instantiating the Consumer class. So you won't be able to obtain this information, especially not from the stack trace.

This is an XY problem. If you need to know who is calling a class, you're doing something wrong. What you could be looking for, is a parameterized constructor in Provider, that gets called with different parameters depending on who needs it, in order to alter its behavior. But that's a different question altogether.

For the latter, see for example .NET Core DI, ways of passing parameters to constructor.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272