/// <summary> /// Resolve condition parameter attribute. /// </summary> /// <param name="nameOfAttribute">Name of attribute</param> /// <returns>Condition Parameter attribute</returns> private static ConditionParameterAttribute ResolveConditionParameter(string nameOfAttribute) { // If the name is empty, return null if (string.IsNullOrEmpty(nameOfAttribute)) { return(null); } // The custom attribute must start with ConditionParameter, // so we do not try to instantiate all kinds of custom attributes if (!nameOfAttribute.Contains(ConditionParameterName)) { return(null); } ConditionParameterAttribute cpa = null; // Check if it is in the cache if (_conditionParameterAttributesCache.TryGetValue(nameOfAttribute, out cpa)) { return(cpa); } else { // Not in the cache, try to resolve it. // Look up the assembly containing the filter modules System.Reflection.Assembly assembly = typeof(ConditionParameterAttribute).Assembly; // TODO This does not allow us to use other assemblies. if (assembly == null) { return(null); } Type type = assembly.GetType(nameOfAttribute, false, true); // If we could not find the type, return null if (type == null) { return(null); } // Create an instance try { cpa = Activator.CreateInstance(type) as ConditionParameterAttribute; } catch { return(null); } // Check for null if (cpa == null) { return(null); } // Add to cache _conditionParameterAttributesCache.Add(nameOfAttribute, cpa); return(cpa); } }
/// <summary> /// Visits the condition literal. /// </summary> /// <remarks> /// Generate a call to a condition. This is a call to a boolean method. /// </remarks> /// <param name="conditionLiteral">The condition literal.</param> public void VisitConditionLiteral(ConditionLiteral conditionLiteral) { // Get the condition Condition con = GetConditionByName(conditionLiteral.Name); if (con == null) { throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.ConditionNotFound, conditionLiteral.Name)); } // Get the parenttype TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(_visitor.Method.DeclaringType); // Get the method MethodReference method; FieldDefinition target = null; // Check if this is an inner or self target. if (con.Reference.Target != null && (con.Reference.Target.Equals(Reference.InnerTarget) || con.Reference.Target.Equals(Reference.SelfTarget) )) { method = CecilUtilities.ResolveMethod( con.Reference.Selector, WeaveType.Name, con.Reference.Assembly, String.Empty); } else if (con.Reference.Target != null && (IsInternal(con.Reference.Target) || IsExternal(con.Reference.Target)) ) { if (!Method.HasThis) { throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.StaticReferenceInternalExternal, Method.Name, Method.DeclaringType.FullName)); } target = parentType.Fields.GetField(con.Reference.Target); TypeDefinition fieldType = CecilUtilities.ResolveTypeDefinition(target.FieldType); MethodDefinition md = CecilUtilities.ResolveMethod(fieldType, con.Reference.Selector, new Type[0]); // If method with no parameters cannot be found, try to find method with JPC context as parameter if (md == null) { md = CecilUtilities.ResolveMethod(fieldType, con.Reference.Selector, m_JpcTypes); } if (md == null) { throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.MethodNotFound2, con.Reference.Selector, con.Reference.Target, fieldType.FullName)); } method = _visitor.TargetAssemblyDefinition.MainModule.Import(md); } else { method = CecilUtilities.ResolveMethod( con.Reference.Selector, con.Reference.FullTypeName, con.Reference.Assembly, String.Empty); } // If we could not find the condition method, throw an exception if (method == null) { throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.MethodNotFound, con.Reference.Selector, con.Reference.FullTypeName, con.Reference.Assembly)); } // If it is an inner or self call, we set the InnerCall context if (con.Reference.Target != null && (con.Reference.Target.Equals(Reference.InnerTarget) || con.Reference.Target.Equals(Reference.SelfTarget) )) { // Set innercall context if (con.Reference.InnerCallContext >= 0) { // Load the this parameter if (!Method.HasThis) { Instructions.Add(Worker.Create(OpCodes.Ldnull)); } else { Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This)); } // Load the methodId Instructions.Add(Worker.Create(OpCodes.Ldc_I4, con.Reference.InnerCallContext)); // Call the SetInnerCall Instructions.Add(Worker.Create(OpCodes.Call, CreateMethodReference(typeof(FilterContext).GetMethod("SetInnerCall", new Type[] { typeof(object), typeof(int) })))); } // Load the this pointer Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This)); } // internal/external and not static: else if (target != null && method.HasThis) { // Load the this pointer Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This)); // Load the field Instructions.Add(Worker.Create(OpCodes.Ldfld, target)); } // else do nothing, because of static call // Convert to a method definition so we can inspect the custom attributes MethodDefinition methodDef = (MethodDefinition)method; if (methodDef != null) { // Find a custom attribute to use foreach (CustomAttribute ca in methodDef.CustomAttributes) { // Retrieve the type name of the custom attribute String typeName = ca.Constructor.DeclaringType.ToString(); // Check if the custom attribute is called ConditionParameter so we do not activate all kinds of attributes if (typeName.Contains(ConditionParameterName)) { // Resolve the CP ConditionParameterAttribute cpa = ResolveConditionParameter(typeName); // Do we have a CPA? if (cpa != null) { // Check if the condition is valid for this code generation if (cpa.IsValidCondition(methodDef)) { // Generate the code needed for this condition cpa.Generate(_visitor, Method, methodDef); } else { // Throw an exception since the condition is not valid. We cannot create valid code for this. throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.ConditionParameterInvalid, typeName, methodDef.ToString(), cpa.RequiredCondition)); } } else { // Throw an exception, we cannot create the custom attribute throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.ConditionParameterNotFound, typeName)); } // Quit the for loop. If there are more custom attributes, we simply skip them. break; } } } // Check if we have to add the JPC // Legacy code, should be able to do this using the ConditionParameter? if (method.Parameters.Count == 1) { if (method.Parameters[0].ParameterType.FullName.Equals(typeof(JoinPointContext).FullName)) { VariableDefinition jpcVar = _visitor.CreateJoinPointContextLocal(); Instructions.Add(Worker.Create(OpCodes.Ldloc, jpcVar)); } } // Create a call instruction Instructions.Add(Worker.Create(OpCodes.Call, TargetAssemblyDefinition.MainModule.Import(method))); }