// Use indexing on generic methods to provide a new reflected method with targets bound with // the supplied type arguments. public object this[object key] { get { // Retrieve the list of type arguments from the index. Type[] types; Tuple typesTuple = key as Tuple; if (typesTuple != null) { types = new Type[typesTuple.Count]; for (int i = 0; i < types.Length; i++) { types[i] = Converter.ConvertToType(typesTuple[i]); } } else { types = new Type[] { Converter.ConvertToType(key) }; } // Start building a new ReflectedMethod that will contain targets with bound type // arguments. ReflectedMethod rm = new ReflectedMethod(); // Search for generic targets with the correct arity (number of type parameters). // Compatible targets must be MethodInfos by definition (constructors never take // type arguments). int arity = types.Length; foreach (MethodBase mb in targets) { MethodInfo mi = mb as MethodInfo; if (mi == null) { continue; } if (mi.ContainsGenericParameters && mi.GetGenericArguments().Length == arity) { rm.AddMethod(mi.MakeGenericMethod(types)); } } if (rm.Targets == null) { throw Ops.TypeError(string.Format("bad type args to this generic method {0}", this)); } rm.Name = Name; rm.FunctionType = FunctionType | FunctionType.OptimizeChecked; // don't want to optimize & whack our dictionary. rm.inst = inst; return(rm); } set { throw new NotImplementedException(); } }
public object this[object key] { get { // Retrieve the signature from the index. Type[] sig; Tuple sigTuple = key as Tuple; if (sigTuple != null) { sig = new Type[sigTuple.Count]; for (int i = 0; i < sig.Length; i++) { sig[i] = Converter.ConvertToType(sigTuple[i]); } } else { sig = new Type[] { Converter.ConvertToType(key) }; } // We can still end up with more than one target since generic and non-generic // methods can share the same name and signature. So we'll build up a new // reflected method with all the candidate targets. A caller can then index this // reflected method if necessary in order to provide generic type arguments and // fully disambiguate the target. ReflectedMethod rm = new ReflectedMethod(); rm.Name = function.Name; rm.FunctionType = function.FunctionType | FunctionType.OptimizeChecked; // don't allow optimization that would whack the real entry rm.inst = function.inst; // Search for targets with the right number of arguments. int args = sig.Length; foreach (MethodBase mb in function.Targets) { ParameterInfo[] pis = mb.GetParameters(); if (pis.Length != args) { continue; } // Check each parameter type for an exact match. bool match = true; for (int i = 0; i < args; i++) { if (pis[i].ParameterType != sig[i]) { match = false; break; } } if (!match) { continue; } // Okay, we have a match, add it to the list. rm.AddMethod(mb); } if (rm.Targets == null) { throw Ops.TypeError("No match found for the method signature {0}", key); } return(rm); } set { throw new NotImplementedException(); } }