Search code examples
c#.netguid.net-4.7.2service-model

Argument to method seems to lose scope when method is invoked


This is a confusing problem for me. I'm passing a Guid into a method from a different DLL, and that Guid, as an argument, seems to lose scope - the Guid retains random values before the first two hyphens, but anything after is strangely zeroed out. The DLL represents code that is also running as a Windows Service, but I stopped the Windows Service and still notice the same behavior).

Guid before method call (which is the correct Guid): e808b3fa-ab7c-48fc-8224-535e41393532

Guid after method call: b287a7d0-00d5-0000-0000-000000000000 (I've run the debugger several times, and the Guid always changes, but seems to always be zeroed out after the second hyphen)

I think I've explained the issue already, but in case code makes things more clear, here's a somewhat minimal code example:

// Service.Business.Service.cs
public static class Service
{
    internal static readonly CalendarService.ClientProxy.Calendar TradingCalendar;

    static Service()
    {
        TradingCalendar = CalendarService.ClientProxy.Service.Calendars.GetCalendarByUidOrThrow(ServiceSettings.Instance.TradingCalendarUid); // value of ServiceSettings.Instance.TradingCalendarUid is e808b3fa-ab7c-48fc-8224-535e41393532 when debugger paused on this line
    }
    public static void Initialize()
    {
    }
}
// Service.Business.ServiceSettings.cs
public class ServiceSettings : SettingsBase
{
    private static readonly ServiceSettings _Instance = new ServiceSettings();
    public static ServiceSettings Instance { get { return _Instance; } }
    public Guid TradingCalendarUid { get; private set; }
}
// Calendar.CalendarService.ClientProxy.Calendars.cs
public class Calendars : ClientWrapperCacheBase<CalendarDto, Calendar, Guid>, IEnumerable<Calendar>, IEnumerable
{
    public Calendar GetCalendarByUidOrThrow(Guid calendarUid)
    {
        Calendar calendarByUid = GetCalendarByUid(calendarUid); // value of calendarUid is b287a7d0-00d5-0000-0000-000000000000 when debugger paused on this line
    }
}

And my functional test I'm using to debug this issue:

[TestMethod]
public void ServiceConstructor()
{
    Service.Business.Service.Initialize();
}

It should be noted that others developed this codebase, and I'm somewhat new to it. I don't think this issue was happening before my code changes (as this is a production codebase), wherein I'm in the middle of upgrading from on-premise ServiceBus to Azure Cloud hosted ServiceBus across all the windows services.

EDIT (answer to "Where is TradingCalendarUid set?"):

(TradingCalendarUid corresponds to a column from a row in a (MS) SQL Server table... I assumed this information was trivial, but providing this code here in case it sheds light on things.)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

// namespace name omitted

public abstract class SettingsBase
{
    private readonly bool ThrowOnMissingSettings;

    public SettingsBase(bool throwOnMissingSettings = false)
    {
        ThrowOnMissingSettings = throwOnMissingSettings;
    }

    protected abstract List<SettingData> OnLoad();

    protected void Load()
    {
        Type type = GetType();
        List<SettingData> list = OnLoad();
        if (list == null)
        {
            list = new List<SettingData>();
        }
        if (ThrowOnMissingSettings)
        {
            List<string> list2 = (from property in type.GetProperties()
                join setting in list on property.Name equals setting.Name into setting_join
                from _setting in setting_join.DefaultIfEmpty()
                where _setting == null
                select property.Name).ToList();
            if (list2.Count > 0)
            {
                throw new Exception("Missing configuration: " + string.Join(", ", list2));
            }
        }
        foreach (SettingData item in list)
        {
            PropertyInfo property2 = type.GetProperty(item.Name);
            if (property2 == null)
            {
                throw new Exception($"Invalid Setting. Name: {item.Name}");
            }
            TypeConverter converter = TypeDescriptor.GetConverter(property2.PropertyType);
            if (converter == null)
            {
                throw new Exception($"Converter not found. Type: {property2.PropertyType}");
            }
            property2.SetValue(this, converter.ConvertFromInvariantString(item.Value), null);
        }
    }
}

Solution

  • I screen-shared with a colleague a couple days ago, and the problem was simply that I had two versions of a DLL in use. One version was being used in my main service, and the old version of the DLL was being used in the windows-service service that was already running, and which my main service in question was connecting to. That's why when I stepped into the method from the other windows service, the argument seemed to lose scope (perhaps it did actually lose scope). Once I made sure that the windows service had the correct reference to the updated DLL, everything mentioned here worked as expected.

    As an aside, I later reproduced the error (more minimally) without even using the class-based field, and simply hard-coding a new Guid, like so: TradingCalendar = CalendarService.ClientProxy.Service.Calendars.GetCalendarByUidOrThrow(new Guid("e808b3fa-ab7c-48fc-8224-535e41393532"));.