/// <summary> /// 使用处理器的委托列表初始化 <see cref="ProcessorData"/> 类的新实例。 /// </summary> /// <param name="delegates">使用不同子类作为参数的委托列表。</param> /// <exception cref="ArgumentException">处理器的参数不匹配。</exception> /// <exception cref="ArgumentException">没有找到唯一的关键参数。</exception> public ProcessorData(Delegate[] delegates) { Contract.Requires(delegates != null && delegates.All(d => d != null)); this.IsStatic = true; List <MethodInfo> list = new List <MethodInfo>(delegates.Length); list.AddRange(delegates.Select(d => d.GetInvokeMethod())); int cnt = list.Count; // 发现关键参数,所有处理器各不相同的参数就认为是关键参数。 List <Type[]> paramTypes = new List <Type[]>(cnt); for (int i = 0; i < cnt; i++) { paramTypes.Add(list[i].GetParameterTypesWithReturn()); } this.KeyIndex = FindKeyIndex(null, null, paramTypes); // 构造委托类型。 this.DelegateParamTypes = FindDelegateType(paramTypes, null); this.DelegateType = Expression.GetDelegateType(this.DelegateParamTypes); this.Processors = new Dictionary <Type, Delegate>(cnt); for (int i = 0; i < cnt; i++) { Type keyType = list[i].GetParameters()[this.KeyIndex].ParameterType; // 经过前面的类型检查,包装委托时应当总是会成功。 this.Processors.Add(keyType, DelegateBuilder.Wrap(this.DelegateType, delegates[i])); } }
/// <summary> /// 使用处理器所属的类型和标识初始化 <see cref="ProcessorData"/> 类的新实例。 /// </summary> /// <param name="type">处理器所属的类型。</param> /// <param name="id">处理器的标识。</param> /// <exception cref="ArgumentException">没有找到处理器。</exception> /// <exception cref="ArgumentException">处理器中混杂着静态和动态方法。</exception> /// <exception cref="ArgumentException">处理器的参数不匹配。</exception> /// <exception cref="ArgumentException">没有找到唯一的关键参数。</exception> public ProcessorData(Type type, string id) { Contract.Requires(type != null && id != null); // 寻找处理器。 MethodInfo[] methods = type.GetMethods(TypeExt.AllMemberFlag); List <MethodInfo> list = new List <MethodInfo>(methods.Length); list.AddRange(methods.Where(m => m.GetCustomAttributes(typeof(ProcessorAttribute), true) .Cast <ProcessorAttribute>().Any(p => p.Id == id))); int cnt = list.Count; if (cnt == 0) { throw CommonExceptions.ProcessorNotFound(type, id); } // 判断是静态方法还是动态方法。 this.IsStatic = list[0].IsStatic; if (list.Any(m => m.IsStatic != IsStatic)) { throw CommonExceptions.ProcessorMixed(type, id); } // 发现关键参数,所有处理器各不相同的参数就认为是关键参数。 List <Type[]> paramTypes = new List <Type[]>(cnt); for (int i = 0; i < cnt; i++) { paramTypes.Add(list[i].GetParameterTypesWithReturn()); } this.KeyIndex = FindKeyIndex(type, id, paramTypes); // 构造委托类型。 this.DelegateParamTypes = FindDelegateType(paramTypes, this.IsStatic ? null : type); this.DelegateType = Expression.GetDelegateType(this.DelegateParamTypes); this.Processors = new Dictionary <Type, Delegate>(cnt); for (int i = 0; i < cnt; i++) { Type keyType = list[i].GetParameters()[this.KeyIndex].ParameterType; // 经过前面的类型检查,创建委托时应当总是会成功。 this.Processors.Add(keyType, DelegateBuilder.CreateDelegate(this.DelegateType, list[i])); } }
/// <summary> /// 返回与指定标识符相关的处理器方法集合。 /// </summary> /// <typeparam name="TDelegate">使用基类型调用方法的委托。</typeparam> /// <param name="type">在其中查找静态或实例方法的类型。</param> /// <param name="id">方法切换器的标识符。</param> /// <param name="index">方法的关键参数索引。</param> /// <param name="queryStatic">是否请求的是静态方法。</param> /// <returns>与指定标识符相关的处理器方法集合。</returns> private static Dictionary <Type, Delegate> GetMethods <TDelegate>(Type type, string id, int index, bool queryStatic) { Type dlgType = typeof(TDelegate); Tuple <bool, Type, Dictionary <Type, Delegate> > data; string key = string.Concat(type.FullName, "_", id); if (!methodDict.TryGetValue(key, out data)) { MethodInfo[] methods = type.GetMethods(MethodFlags); List <MethodInfo> list = new List <MethodInfo>(); for (int i = 0; i < methods.Length; i++) { if (methods[i].GetCustomAttributes(typeof(ProcessorAttribute), true) .Cast <ProcessorAttribute>().Any(s => s.Id == id)) { list.Add(methods[i]); } } int cnt = list.Count; if (cnt == 0) { throw ExceptionHelper.ProcessorNotFound("type", type, id); } bool isStatic = list[0].IsStatic; for (int i = 1; i < cnt; i++) { if (list[i].IsStatic != isStatic) { throw ExceptionHelper.ProcessorMixed("type", type, id); } } Dictionary <Type, Delegate> dict = new Dictionary <Type, Delegate>(); Type newDlgType = dlgType; if (!isStatic) { newDlgType = GetInstanceDlgType(newDlgType); } for (int i = 0; i < cnt; i++) { Type keyType = list[i].GetParameters()[index].ParameterType; Delegate dlg = DelegateBuilder.CreateDelegate(newDlgType, list[i], false); if (dlg == null) { throw ExceptionHelper.DelegateCompatible(list[i].ToString(), dlgType); } dict.Add(keyType, dlg); } data = new Tuple <bool, Type, Dictionary <Type, Delegate> >(isStatic, dlgType, dict); methodDict.Add(key, data); } if (data.Item1 != queryStatic) { throw ExceptionHelper.ProcessorMismatch("type", type, id); } if (data.Item2 != dlgType) { // 检查委托参数。 ParameterInfo[] paramInfos = data.Item2.GetMethod("Invoke").GetParameters(); ParameterInfo[] dlgParamInfos = dlgType.GetMethod("Invoke").GetParameters(); if (paramInfos.Length != dlgParamInfos.Length) { throw ExceptionHelper.DelegateCompatible("TDelegate", dlgType); } for (int i = 0; i < paramInfos.Length; i++) { if (paramInfos[i].ParameterType != dlgParamInfos[i].ParameterType) { throw ExceptionHelper.DelegateCompatible("TDelegate", dlgType); } } } return(data.Item3); }