Lars Baunwall
Lars Baunwall

Reputation: 75

StructureMap and logical call contexts

I have a peculiar problem with StructureMap.

Whenever I construct an object, that spawns a new thread, the logical Call context (System.Runtime.Remoting.Messaging.CallContext) becomes empty:

class Program
{
    static void Main(string[] args)
    {
        Container c = new Container(map =>
        {
            map.For<PersistedObject>().Use(new PersistedObject());
        });


        CallContext.LogicalSetData("myvar", "Logical call context variable");
        Console.WriteLine($"Main: {Thread.CurrentThread.ManagedThreadId}: {CallContext.LogicalGetData("myvar")}");

        var obj = c.GetInstance<PersistedObject>();

        obj.Print("IoC");
        Console.WriteLine("--------------------");
        new PersistedObject().Print("Constructed");

        Console.ReadLine();
    }

    public class PersistedObject
    {
        public PersistedObject()
        {
            Console.WriteLine($"Ctor: {Thread.CurrentThread.ManagedThreadId}: {CallContext.LogicalGetData("myvar")}");
            Thread t = new Thread(() => Print("Thread"));

            t.Start();
        }
        public void Print(string message)
        {
            Console.WriteLine($"{message}: {Thread.CurrentThread.ManagedThreadId}: {CallContext.LogicalGetData("myvar")}");
        }
    }
}

The above code gives these results:

   Main: 10: Logical call context variable 
   Ctor: 10: <Null> 
   Thread: 11: <Null> 
   IoC: 10: Logical call context variable
   -------------- 
   Ctor: 10: Logical call context variable 
   Constructed: 10: Logical call context variable 
   Thread: 12: Logical call context variable 

As you can see, when the logical call context is accessed in the constructor (or the thread that is spawned in the constructor), it doesn't work with StructureMap.

Anyone have an idea about why?

Upvotes: 0

Views: 126

Answers (1)

khellang
khellang

Reputation: 18112

You're creating an instance of PersistedObject before the call to CallContext.LogicalSetData

Container c = new Container(map =>
{
    map.For<PersistedObject>().Use(new PersistedObject()); // <-- This is calling the ctor.
});

CallContext.LogicalSetData("myvar", "Logical call context variable");

If you change the code above to

Container c = new Container(map =>
{
    map.For<PersistedObject>().Use<PersistedObject>(); // <-- No ctor call
});

CallContext.LogicalSetData("myvar", "Logical call context variable");

You should get the correct output.

Upvotes: 1

Related Questions