Static Command instantiated twice

Topics: Prism v1
Feb 15, 2009 at 9:23 PM
Hi all,

I have been having a strange problem with static Commands and DataTemplates.  I used the code from the StockTraderRI sample for creating a globally available command:
In the infrastructure project I have:
namespace Infrastructure
{
    public static class NexNeuroCommands
    {
        static CompositeCommand openModuleCommand;
        public static CompositeCommand OpenModuleCommand
        {
            get
            {
                if (openModuleCommand == null)
                    openModuleCommand = new CompositeCommand();
                return openModuleCommand;
            }
        }

        public static CompositeCommand CloseModuleCommand = new CompositeCommand();
    }

    public class NexNeuroCommandProxy ...
}
I created the OpenModuleCommand as a property so that I could break on the openModuleCommand = new CompositeCommand(); line.  Other than that, the code is "by the book".

Next, there is a class that registers for the command:
    public class NexNeuroModuleHandler : INexNeuroModuleHandler
    {
        private readonly IRegionManager _regionManager;
        private NexNeuroCommandProxy commandProxy;
        public NexNeuroModuleHandler(IRegionManager regionManager, NexNeuroCommandProxy commandProxy)
        {
            _regionManager = regionManager;
            this.commandProxy = commandProxy;
            OpenModuleCommand = new DelegateCommand<string>(OnOpenModule);
            commandProxy.OpenModuleCommand.RegisterCommand(OpenModuleCommand);
        }
        void OnOpenModule(string str)
        {
            System.Windows.MessageBox.Show("Womp here I am");
        }
        #region INexNeuroModuleHandler Members
        #endregion
        public DelegateCommand<string> OpenModuleCommand { get; private set; }
    }

Again, this is by the book, straight from the OrderController in the StockTraderRI sample.

Finally, here is the DataTemplate that sends the command and the initialization code:
    <DataTemplate x:Key="ModuleListBarItem">
        <Button Command="src:NexNeuroCommands.OpenModuleCommand" CommandParameter="Hello">
            <StackPanel>
                <Image Name="MainButton" Source="{Binding Path=ModuleBarImageResource}" />
                <TextBlock Text="{Binding Path=Title}" />
            </StackPanel>
        </Button>
    </DataTemplate>

This template is loaded and attached to the ItemsControl in the following code:
        private void RegisterViews()
        {
            IRegion moduleSelectionRegion = _regionManager.Regions[RegionNames.ModuleSelectionRegion];
            ModuleListBar view = new ModuleListBar();
            Binding b = new Binding("Modules");
            b.Source = _unityContainer.Resolve<INexNeuroModuleHandler>();
            BindingOperations.SetBinding(view, ModuleListBar.ItemsSourceProperty, b);
            ResourceDictionary rd = new ResourceDictionary();
            rd.Source = new Uri("NexNeuroControls;component/NexNeuroResources.xaml", UriKind.Relative);
            Application.Current.Resources.MergedDictionaries.Add(rd);
            view.Template = (ControlTemplate)Application.Current.Resources["ModuleListBar"];
            view.ItemTemplate = (DataTemplate)Application.Current.Resources["ModuleListBarItem"];
            view.ItemsPanel = (ItemsPanelTemplate)Application.Current.Resources["ModuleListBarItemsPanelTemplate"];
            view.ItemContainerStyle = (Style)Application.Current.Resources["ModuleListBarItemContainerStyle"];
            view.Height = 100;
            moduleSelectionRegion.Add(view);
            moduleSelectionRegion.Activate(view);
        }

The problem that I am having is that the openModuleCommand = new CompositeCommand(); line (way up top) is being executed twice!  So, the controls have a different instance of the static command than the NexNeuroModuleHandler that registers for the command.  I am confused as to how this could happen, but mostly, I am looking for a workaround.

Any ideas out there?

Thanks for your help.

Regards,
Wayne.
Feb 16, 2009 at 11:26 AM
Edited Feb 16, 2009 at 11:47 AM
Hi Wayne,
Doing the new up in the getter might be causing concurrency issues, where the getter might be being called twice at the same time, and causing a race condition when reading and writing the field.
The ieasiest way to solve it if this is the issue, is by having a static field that is autoinitialized, but you won't be able to put a breakpoint as you suggested (you might put it in the static constructor though.
Another way is to put a locking mechanism, but that would be more unnecesarily complex than you probably want in your code, if you can avoid it:

namespace Infrastructure
{
    public static class NexNeuroCommands
    {
        static lockObject = new object();
        static CompositeCommand openModuleCommand;
        public static CompositeCommand OpenModuleCommand
        {
            get
            {
                if (openModuleCommand == null)
                    lock (lockObject)
                    {
                             if (openModuleCommand == null)
                                     openModuleCommand = new CompositeCommand();
                     }
                return openModuleCommand;
            }
        }

    }
}


Hope this helps,
Julian Dominguez

Feb 16, 2009 at 12:22 PM
Thanks for the answer, Julian.

After banging my head for several hours and getting a massive headache, I finally figured out that the Infrastructure assembly was being loaded twice: once from my modules directory (I am using the ConfigurationModuleEnumerator, with the config file pointing to modules\Infrastructure.dll), and once from the current directory.  So, each time I referenced NexNeuroCommands.OpenModuleCommand, it was from a different assembly, therefore the type was reinitialized.

I pointed the config file to the current directory version of Infrastructure.dll and it works now.

Best regards,
Wayne.