// -------------------------------------------------------------------------------------------- /// <summary> /// Merges menu information with the specified target information. /// </summary> /// <param name="target">Target to merge the menu into.</param> /// <param name="info">Menu command information to merge.</param> // -------------------------------------------------------------------------------------------- private static void MergeCommandMethodInfo(CommandTargetInfo target, MenuCommandInfo info) { // --- Apply mappings foreach (var mapping in target.Mappings) { // --- Check for mapping GUID if ((mapping.Guid == Guid.Empty && info.Guid == target.DefaultGuid) || mapping.Guid != info.Guid) { // --- Mapping GUID matches, check for ID range if (info.Id >= mapping.IdFrom && info.Id <= mapping.IdTo) { // --- ID in the mapping range, apply offset info.Id = (uint)((int)info.Id + mapping.Offset); break; } } } // --- Actual merging starts here Dictionary <uint, MenuCommandInfo> commandsForGroup; if (!target.TryGetValue(info.Guid, out commandsForGroup)) { // --- No item exists for the command group. commandsForGroup = new Dictionary <uint, MenuCommandInfo> { { info.Id, info } }; target.Add(info.Guid, commandsForGroup); return; } MenuCommandInfo mergedInfo; if (!commandsForGroup.TryGetValue(info.Id, out mergedInfo)) { // --- No item with info.id in the command group. commandsForGroup.Add(info.Id, info); return; } // --- Merge with the former items mergedInfo.Promote |= info.Promote; if (info.ChangeMethod != null) { if (mergedInfo.ChangeMethod == null) { mergedInfo.ChangeMethod = info.ChangeMethod; } else { throw new InvalidOperationException(Resources.CommandDispatcher_DuplicateChange); } } if (info.ExecMethod != null) { if (mergedInfo.ExecMethod == null) { mergedInfo.ExecMethod = info.ExecMethod; mergedInfo.Action = info.Action; } else { throw new InvalidOperationException(Resources.CommandDispatcher_DuplicateExec); } } if (info.QueryStatusMethod != null) { if (mergedInfo.QueryStatusMethod == null) { mergedInfo.QueryStatusMethod = info.QueryStatusMethod; } else { throw new InvalidOperationException(Resources.CommandDispatcher_DuplicateStatus); } } }
// -------------------------------------------------------------------------------------------- /// <summary> /// Scans through all the methods of the EventTarget's type to collect information about /// command handler methods. /// </summary> // -------------------------------------------------------------------------------------------- private void ScanDispatchInfo() { Type targetType = EventTarget.GetType(); lock (_Targets) { // --- We scan only the type info, if we have not scanned it yet. if (_Targets.ContainsKey(targetType)) { return; } var target = new CommandTargetInfo(); // --- Obtain the default command Guid for the event target var defaultGuidAttr = targetType.GetAttribute <DefaultCommandGroupAttribute>(); Guid defaultGuid = defaultGuidAttr == null ? (GuidProvider == null ? targetType.GUID : GuidProvider.CommandGuid) : defaultGuidAttr.Value.GUID; target.DefaultGuid = defaultGuid; // --- Obtain command mapping information var mappings = targetType.AttributesOfType <CommandMapAttribute>(); foreach (var attr in mappings) { target.Mappings.Add(attr); } // --- Obtain all methods that can be used as command methods var commandMethods = from method in targetType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) where method.ReturnType == typeof(void) && ( // --- void MyCommandExec() method.GetParameters().Count() == 0 && Attribute.IsDefined(method, typeof(CommandExecMethodAttribute)) || // --- void MyCommandExec(CommandContext) method.GetParameters().Count() == 1 && ( method.GetParameters()[0].ParameterType == typeof(CommandContext) || method.GetParameters()[0].ParameterType.IsSubclassOf(typeof(CommandContext)) ) && Attribute.IsDefined(method, typeof(CommandExecMethodAttribute)) || // --- void MyCommandMethod(OleMenuCommand) method.GetParameters().Count() == 1 && method.GetParameters()[0].ParameterType == typeof(OleMenuCommand) && Attribute.IsDefined(method, typeof(CommandMethodAttribute)) || // --- void MyCommandMethod(OleMenuCommand, CommandExec) method.GetParameters().Count() == 2 && method.GetParameters()[0].ParameterType == typeof(OleMenuCommand) && ( method.GetParameters()[1].ParameterType == typeof(CommandContext) || method.GetParameters()[1].ParameterType.IsSubclassOf(typeof(CommandContext)) ) && Attribute.IsDefined(method, typeof(CommandMethodAttribute)) ) && Attribute.IsDefined(method, typeof(CommandIdAttribute)) select method; foreach (var method in commandMethods) { foreach (CommandIdAttribute idAttr in method.GetCustomAttributes(typeof(CommandIdAttribute), false)) { var menuInfo = ObtainCommandMethodAttributes(idAttr, method, defaultGuid); MergeCommandMethodInfo(target, menuInfo); } } _Targets.Add(targetType, target); } }