Command pattern with MEF

Jul 21, 2010 at 7:39 AM

Hello,

I'm strugling implementing Command pattern with MEF. I have an action manager which stores different actions which will be executed through the menu.

public interface IActionManager
    {
        void ExecuteAction(ActionType actionType);
        bool CanExecuteAction(ActionType actionType);
    }

    [Export(typeof(IActionManager))]
    public sealed class ActionManager : IActionManager, IPartImportsSatisfiedNotification
    {
        private readonly IDictionary<IActionMetadata, Action> _actions = new Dictionary<IActionMetadata, Action>();

        [ImportMany(AllowRecomposition = true)]
        public ObservableCollection<Lazy<Action, IActionMetadata>> Actions { get; set; }

       public void OnImportsSatisfied()
        {
            lock (_actions)
            {
                updateActions();
            }
        }

        private void updateActions()
        {
            if (Actions == null || Actions.Count <= 0)
                return;

            foreach (Lazy<Action, IActionMetadata> imported in Actions)
            {
                _actions.Add(new KeyValuePair<IActionMetadata, Action>(imported.Metadata, imported.Value));
            }

        }

        public void ExecuteAction(ActionType actionType)
        {
            lock (_actions)
            {
                if (CanExecuteAction(actionType))
                {
                    getCurrentAction(actionType).Value();
                }
            }
        }

        public bool CanExecuteAction(ActionType actionType)
        {
            lock (_actions)
            {
                return getCurrentAction(actionType).Value != null;
            }
        }

        private KeyValuePair<IActionMetadata, Action> getCurrentAction(ActionType actionType)
        {
            Type targetType = typeof(MyControl);
            return getAction(targetType, actionType);
        }

        private KeyValuePair<IActionMetadata, Action> getAction(Type targetType, ActionType actionType)
        {
           
            return _actions.Where(a => a.Key.TargetType == targetType && a.Key.ActionType == actionType).
                FirstOrDefault();
        }
    }
And I also have a et of controls each implemets zero or more actions:
[Export]
public partial class Details : Page, IPartImportsSatisfiedNotification
    {
       
        [Import]
        public ICustomerService CustomerService { get; set; }
        
        public Details()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            PartInitializer.SatisfyImports(this);
        }

        [ExportAction(TargetType = typeof(Details), ActionType = ActionType.Save)]
        public void OnSaveClicked()
        {
           // save customer
        }

        [ExportAction(TargetType = typeof(Details), ActionType = ActionType.Delete)]
        public void OnDeleteClicked()
        {
            // delete customer
        }

        public void OnImportsSatisfied()
        {
            // set up UI
        }
    }
So I stuck with the problem that ActionManager actuall might have several 'Save' and 'Delete' actions for my Details view depends on how many times it was instantiated. Is there a way to make those controls 'static' accross the app ?
Or maybe someone can suggest a better practice for Command pattern with MEF ?