/// <summary> /// Implements the .GetTypes method which returns a list of all annotated RDF classes for a given type. /// </summary> /// <param name="parameter">A type defintion.</param> /// <returns><c>true</c> on success, <c>false</c> otherwise.</returns> public override bool Execute(object parameter = null) { List <string> uris = new List <string>(); // Accumulate the annotated RDF classes. foreach (CustomAttribute attribute in Type.TryGetCustomAttribute("RdfClassAttribute")) { uris.Insert(0, attribute.ConstructorArguments.First().Value.ToString()); } if (uris.Count == 0) { if (!Type.Methods.Any(m => m.Name == "GetTypes")) { string msg = "{0}: Mapped type has no annotated RDF classes and no overridden GetTypes() method."; throw new Exception(string.Format(msg, Type.FullName)); } return(false); } TypeDefinition[] types = { Type }; MethodDefinition getTypes = null; MethodReference getTypeBase = null; // We iterate through the type hierarchy from top to bottom and find the first GetTypes // method. That one serves as a template for the override method of the current type in // which the instructions are being replaced. foreach (TypeDefinition t in types.Union(Type.GetBaseTypes()).Reverse()) { getTypes = t.TryGetInheritedMethod("GetTypes"); if (getTypes != null && getTypeBase == null) { getTypeBase = getTypes; break; } } if (getTypes == null) { throw new ArgumentException("{0}: Found no GetTypes() method for type.", Type.FullName); } if (getTypeBase == null) { throw new ArgumentException(string.Format("{0}: Failed to find virtual base method of {1}", Type.FullName, getTypes.FullName)); } // The override method must be created in the module where the type is defined. getTypes = getTypeBase.GetOverrideMethod(MainModule); MethodGeneratorTask generator = new MethodGeneratorTask(getTypes); generator.Instructions.AddRange(GenerateGetTypesInstructions(generator.Processor, uris)); if (generator.CanExecute()) { generator.Method.Body.MaxStackSize = 3; generator.Method.Body.InitLocals = true; generator.Method.Body.Variables.Add(new VariableDefinition(MainModule.ImportReference(getTypeBase.ReturnType))); generator.Method.Body.Variables.Add(new VariableDefinition(ClassArrayType)); generator.Execute(); MainModule.ImportReference(ClassType); } Type.Methods.Add(getTypes); foreach (string uri in uris) { Log.LogMessage("{0} -> <{1}>", Type.FullName, uri); } return(true); }