private void CustomRead(DslModeling::SerializationContext serializationContext, DslModeling::ModelElement element, global::System.Xml.XmlReader reader) { DefaultRead(serializationContext, element, reader); ConfigurationSectionModel model = (ConfigurationSectionModel)element; // Make sure there's always a Validators instance in the model if (model.PropertyValidators == null) { model.PropertyValidators = new PropertyValidators(model.Store); } }
private void GenerateCustomConverters(ConfigurationSectionModel model, CodeCompileUnit generationUnit) { // Create the namespace block CodeNamespace converterNamespace = new CodeNamespace(model.Namespace); generationUnit.Namespaces.Add(converterNamespace); foreach (CustomTypeConverter converter in model.CustomTypeConverters) { // Create the converter class CodeTypeDeclaration customConverter = new CodeTypeDeclaration(converter.Name); converterNamespace.Types.Add(customConverter); customConverter.Comments.Add(DocComment("<summary>")); if (!string.IsNullOrEmpty(converter.Documentation)) { customConverter.Comments.Add(DocComment(converter.Documentation)); } else { customConverter.Comments.Add(DocComment(string.Format("{0} Custom Converter", converter.Name))); } customConverter.Comments.Add(DocComment("</summary>")); customConverter.Attributes = MemberAttributes.Public; customConverter.IsPartial = true; customConverter.IsClass = true; customConverter.Name = converter.Name; customConverter.BaseTypes.Add(GlobalReference(typeof(System.Configuration.ConfigurationConverterBase))); CodeTypeReference convertType; if (converter.Type is TypeDefinition) { convertType = GlobalReference(converter.Type.FullName); } else { convertType = GlobalSelfReference(converter.Type.FullName); } // Override the ConvertFrom method CodeMemberMethod convertFromMethod = new CodeMemberMethod(); customConverter.Members.Add(convertFromMethod); convertFromMethod.Comments.Add(DocComment("<summary>")); convertFromMethod.Comments.Add(DocComment(string.Format("Converts from <see cref=\"string\" /> to <see cref=\"{0}\" />.", GetTypeReferenceString(convertType)))); convertFromMethod.Comments.Add(DocComment("</summary>")); convertFromMethod.Comments.Add(DocComment(string.Format("<param name=\"context\">The <see cref=\"{0}\" /> that provides a format context.</param>", GetTypeReferenceString(typeof(System.ComponentModel.ITypeDescriptorContext))))); convertFromMethod.Comments.Add(DocComment(string.Format("<param name=\"culture\">The <see cref=\"{0}\" /> to use as the current culture.</param>", GetTypeReferenceString(typeof(System.Globalization.CultureInfo))))); convertFromMethod.Comments.Add(DocComment("<param name=\"value\">The <see cref=\"string\" /> to convert from.</param>")); convertFromMethod.CustomAttributes.Add(_generatedCodeAttribute); convertFromMethod.Attributes = MemberAttributes.Public | MemberAttributes.Override; convertFromMethod.ReturnType = _object; convertFromMethod.Name = "ConvertFrom"; convertFromMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.ComponentModel.ITypeDescriptorContext)), "context")); convertFromMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Globalization.CultureInfo)), "culture")); convertFromMethod.Parameters.Add(new CodeParameterDeclarationExpression(_object, "value")); convertFromMethod.Statements.Add(Comment("IMPORTANT NOTE: The code below does not build by default.")); convertFromMethod.Statements.Add(Comment("This is a custom type validator that must be implemented")); convertFromMethod.Statements.Add(Comment("for it to build. Place the following in a separate file")); convertFromMethod.Statements.Add(Comment("and implement the method.")); convertFromMethod.Statements.Add(Comment("")); // Generate a partial class with a ConvertFromStringToX method, then put that // generated code into the comments for the ConvertFrom // method as an instruction to the user on how to handle the conversion. { CodeTypeDeclaration partialElementDeclaration = new CodeTypeDeclaration(customConverter.Name); partialElementDeclaration.Attributes = MemberAttributes.Public; partialElementDeclaration.IsPartial = true; partialElementDeclaration.IsClass = true; CodeMemberMethod convertFromMethodImplement = new CodeMemberMethod(); partialElementDeclaration.Members.Add(convertFromMethodImplement); convertFromMethodImplement.Attributes = MemberAttributes.Private | MemberAttributes.Final; convertFromMethodImplement.ReturnType = convertType; convertFromMethodImplement.Name = string.Format("ConvertFromStringTo{0}", converter.Type.Name); convertFromMethodImplement.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.ComponentModel.ITypeDescriptorContext)), "context")); convertFromMethodImplement.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Globalization.CultureInfo)), "culture")); convertFromMethodImplement.Parameters.Add(new CodeParameterDeclarationExpression(_string, "value")); // Throw NotImplementedException as per what is normal in generated methods that // are intended to be filled. convertFromMethodImplement.Statements.Add( new CodeThrowExceptionStatement( new CodeObjectCreateExpression( GlobalReference(typeof(NotImplementedException)) ) ) ); // Convert to string and place in comments string generatedCode = CodeTypeDeclarationToString(partialElementDeclaration); foreach (string line in generatedCode.Split(new string[] { "\r\n" }, int.MaxValue, StringSplitOptions.None)) { convertFromMethod.Statements.Add(Comment(line)); } convertFromMethod.Statements.Add(new CodeMethodReturnStatement(new CodeMethodInvokeExpression(_this, convertFromMethodImplement.Name, new CodeArgumentReferenceExpression("context"), new CodeArgumentReferenceExpression("culture"), new CodeCastExpression(_string, new CodeArgumentReferenceExpression("value"))))); } // Override the ConvertTo method CodeMemberMethod convertToMethod = new CodeMemberMethod(); customConverter.Members.Add(convertToMethod); convertToMethod.Comments.Add(DocComment("<summary>")); convertToMethod.Comments.Add(DocComment(string.Format("Converts from <see cref=\"{0}\" /> to <see cref=\"string\" />.", GetTypeReferenceString(convertType)))); convertToMethod.Comments.Add(DocComment("</summary>")); convertToMethod.Comments.Add(DocComment(string.Format("<param name=\"context\">The <see cref=\"{0}\" /> that provides a format context.</param>", GetTypeReferenceString(typeof(System.ComponentModel.ITypeDescriptorContext))))); convertToMethod.Comments.Add(DocComment(string.Format("<param name=\"culture\">The <see cref=\"{0}\" /> to use as the current culture.</param>", GetTypeReferenceString(typeof(System.Globalization.CultureInfo))))); convertToMethod.Comments.Add(DocComment("<param name=\"value\">The <see cref=\"string\" /> to convert from.</param>")); convertToMethod.Comments.Add(DocComment(string.Format("<param name=\"type\">The <see cref=\"{0}\" /> to convert the value parameter to.</param>", GetTypeReferenceString(typeof(System.Type))))); convertToMethod.CustomAttributes.Add(_generatedCodeAttribute); convertToMethod.Attributes = MemberAttributes.Public | MemberAttributes.Override; convertToMethod.ReturnType = _object; convertToMethod.Name = "ConvertTo"; convertToMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.ComponentModel.ITypeDescriptorContext)), "context")); convertToMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Globalization.CultureInfo)), "culture")); convertToMethod.Parameters.Add(new CodeParameterDeclarationExpression(_object, "value")); convertToMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Type)), "type")); convertToMethod.Statements.Add(Comment("IMPORTANT NOTE: The code below does not build by default.")); convertToMethod.Statements.Add(Comment("This is a custom type validator that must be implemented")); convertToMethod.Statements.Add(Comment("for it to build. Place the following in a separate file")); convertToMethod.Statements.Add(Comment("and implement the method.")); convertToMethod.Statements.Add(Comment("")); // Generate a partial class with a ConvertToXFromString method, then put that // generated code into the comments for the ConvertTo // method as an instruction to the user on how to handle the conversion. { CodeTypeDeclaration partialElementDeclaration = new CodeTypeDeclaration(customConverter.Name); partialElementDeclaration.Attributes = MemberAttributes.Public; partialElementDeclaration.IsPartial = true; partialElementDeclaration.IsClass = true; CodeMemberMethod convertToMethodImplement = new CodeMemberMethod(); partialElementDeclaration.Members.Add(convertToMethodImplement); convertToMethodImplement.Attributes = MemberAttributes.Private | MemberAttributes.Final; convertToMethodImplement.ReturnType = _string; convertToMethodImplement.Name = string.Format("ConvertTo{0}FromString", converter.Type.Name); convertToMethodImplement.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.ComponentModel.ITypeDescriptorContext)), "context")); convertToMethodImplement.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Globalization.CultureInfo)), "culture")); convertToMethodImplement.Parameters.Add(new CodeParameterDeclarationExpression(convertType, "value")); convertToMethodImplement.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Type)), "type")); // Suggest a ToString() call convertToMethodImplement.Statements.Add( new CodeMethodReturnStatement( new CodeMethodInvokeExpression( new CodeArgumentReferenceExpression("value"), "ToString" ) ) ); // Convert to string and place in comments string generatedCode = CodeTypeDeclarationToString(partialElementDeclaration); foreach (string line in generatedCode.Split(new string[] { "\r\n" }, int.MaxValue, StringSplitOptions.None)) { convertToMethod.Statements.Add(Comment(line)); } convertToMethod.Statements.Add(new CodeMethodReturnStatement(new CodeMethodInvokeExpression(_this, convertToMethodImplement.Name, new CodeArgumentReferenceExpression("context"), new CodeArgumentReferenceExpression("culture"), new CodeCastExpression(convertType, new CodeArgumentReferenceExpression("value")), new CodeArgumentReferenceExpression("type")))); } } }
public byte[] GenerateCode(string inputFilePath) { using (Store store = new Store(typeof(CoreDesignSurfaceDomainModel), typeof(ConfigurationSectionDesignerDomainModel))) { // Prepare the model ConfigurationSectionModel model = PrepareModel(inputFilePath, store); // Prepare code generator CodeCompileUnit generationUnit = PrepareCodeGenerator(); // Generate code for the configuration elements foreach (BaseConfigurationType type in model.ConfigurationElements) { // Ignore any ConfigurationType that is not an instance of // the ConfigurationElement. ConfigurationElement element = type as ConfigurationElement; if (element == null) { continue; } // Create namespace declaration CodeNamespace elementNamespace = new CodeNamespace(element.ActualNamespace); generationUnit.Namespaces.Add(elementNamespace); // Create the element class and set common options CodeTypeDeclaration elementClass = new CodeTypeDeclaration(element.Name); elementNamespace.Types.Add(elementClass); elementClass.Comments.Add(DocComment("<summary>")); elementClass.Comments.Add(DocComment(EscapeStringChars(element.DocumentationText))); elementClass.Comments.Add(DocComment("</summary>")); elementClass.TypeAttributes = (element.AccessModifier == AccessModifiers.Public) ? TypeAttributes.Public : TypeAttributes.NotPublic; if (element.InheritanceModifier == InheritanceModifiers.Abstract) { elementClass.TypeAttributes |= TypeAttributes.Abstract; } else if (element.InheritanceModifier == InheritanceModifiers.Sealed) { elementClass.TypeAttributes |= TypeAttributes.Sealed; } elementClass.IsPartial = true; elementClass.IsClass = true; if (element.BaseClass != null) { elementClass.BaseTypes.Add(GlobalSelfReference(element.BaseClass.FullName)); } // Set element-type specific options if (element is ConfigurationSection) { // Set base type to be ConfigurationSection if (element.BaseClass == null) { elementClass.BaseTypes.Add(GlobalReference(typeof(System.Configuration.ConfigurationSection))); } // Do custom ConfigurationElementCollection code generation GenerateConfigurationSectionCode(element, elementClass); } else if (element is ConfigurationElementCollection) { // Set base type to be ConfigurationElementCollection if (element.BaseClass == null) { elementClass.BaseTypes.Add(GlobalReference(typeof(System.Configuration.ConfigurationElementCollection))); } // Do custom ConfigurationElementCollection code generation GenerateConfigurationElementCollectionCode(element, elementClass); } else if (element is ConfigurationElement) { // Set base type to be ConfigurationElement if (element.BaseClass == null) { elementClass.BaseTypes.Add(GlobalReference(typeof(System.Configuration.ConfigurationElement))); } } // Set IsReadOnly setting CodeMemberMethod isReadOnlyMethod = new CodeMemberMethod(); elementClass.Members.Add(isReadOnlyMethod); isReadOnlyMethod.StartDirectives.Add(Region("IsReadOnly override")); isReadOnlyMethod.Comments.Add(DocComment("<summary>")); isReadOnlyMethod.Comments.Add(DocComment("Gets a value indicating whether the element is read-only.")); isReadOnlyMethod.Comments.Add(DocComment("</summary>")); isReadOnlyMethod.CustomAttributes.Add(_generatedCodeAttribute); isReadOnlyMethod.Attributes = MemberAttributes.Public | MemberAttributes.Override; isReadOnlyMethod.ReturnType = _bool; isReadOnlyMethod.Name = "IsReadOnly"; isReadOnlyMethod.Statements.Add( new CodeMethodReturnStatement( element.IsReadOnly ? _true : _false ) ); isReadOnlyMethod.EndDirectives.Add(EndRegion()); // Add all the element's properties foreach (ConfigurationProperty property in element.Properties) { GenerateProperty(element, elementClass, property); } if (element.HasCustomChildElements) { GenerateCustomChildElementHandler(elementClass); } } foreach (TypeDefinition type in model.TypeDefinitions) { EnumeratedType enumType = type as EnumeratedType; if (enumType != null && ((enumType.CodeGenOptions & TypeDefinitionCodeGenOptions.TypeDefinition) == TypeDefinitionCodeGenOptions.TypeDefinition)) { // Create the namespace block CodeNamespace typeNamespace = new CodeNamespace(enumType.Namespace); generationUnit.Namespaces.Add(typeNamespace); // Create enum CodeTypeDeclaration enumTypeDeclaration = new CodeTypeDeclaration(enumType.Name); typeNamespace.Types.Add(enumTypeDeclaration); enumTypeDeclaration.Comments.Add(DocComment("<summary>")); if (string.IsNullOrEmpty(enumType.Documentation)) { // If the enum has no documentation, just make the documentation the name of the enum value enumTypeDeclaration.Comments.Add(DocComment(string.Format("{0}.", enumType.Name))); } else { enumTypeDeclaration.Comments.Add(DocComment(EscapeStringChars(enumType.Documentation))); } enumTypeDeclaration.Comments.Add(DocComment("</summary>")); enumTypeDeclaration.CustomAttributes.Add(_generatedCodeAttribute); if (enumType.IsFlags) { enumTypeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration(GlobalReference(typeof(FlagsAttribute)))); } enumTypeDeclaration.Attributes = MemberAttributes.Public; enumTypeDeclaration.IsEnum = true; foreach (EnumerationLiteral literal in enumType.Literals) { CodeMemberField enumField = new CodeMemberField(); enumTypeDeclaration.Members.Add(enumField); enumField.Comments.Add(DocComment("<summary>")); if (string.IsNullOrEmpty(literal.Documentation)) { enumField.Comments.Add(DocComment(string.Format("{0}.", literal.Name))); } else { enumField.Comments.Add(DocComment(EscapeStringChars(literal.Documentation))); } enumField.Comments.Add(DocComment("</summary>")); enumField.Name = literal.Name; if (!string.IsNullOrEmpty(literal.Value)) { enumField.InitExpression = new CodeSnippetExpression(literal.Value); } } } } if (model.PropertyValidators.Validators.Count > 0) { GenerateValidators(model, generationUnit); } if (model.CustomTypeConverters.Count > 0) { GenerateCustomConverters(model, generationUnit); } _generator.GenerateCodeFromCompileUnit(generationUnit, _codeWriter, _options); _codeWriter.Flush(); byte[] output = new byte[_codeStream.Length]; Array.Copy(_codeStream.GetBuffer(), 0, output, 0, _codeStream.Length); return(output); } }
// [Note by Max 20140906] TODO this should create a new appdomain to import an assembly and then unloading it. // If you load an assembly of the current solution you are not able to build anymore // since msbuild is unable to delete the assembly because is currently in use. private void ImportExternalEnum() { OpenFileDialog ofd = new OpenFileDialog() { DefaultExt = "dll", Filter = "Assemblies (*.dll)|*.dll|All Files (*.*)|*.*" }; if (ofd.ShowDialog() == DialogResult.OK) { string file = ofd.FileName; Assembly assembly = Assembly.LoadFrom(file); List <Type> enumTypes = new List <Type>(); foreach (Type type in assembly.GetExportedTypes()) { if (type.IsEnum) { enumTypes.Add(type); } } if (enumTypes.Count == 0) { MessageBox.Show("The chosen assembly has no public Enums.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } ConfigurationSectionDesignerDiagram diagram = this.SingleDocumentSelection as ConfigurationSectionDesignerDiagram; using (Transaction transaction = diagram.Store.TransactionManager.BeginTransaction("Import External Enum")) { using (ImportEnumForm importEnumForm = new ImportEnumForm(enumTypes)) { if (importEnumForm.ShowDialog() == DialogResult.OK) { ConfigurationSectionModel model = diagram.ModelElement as ConfigurationSectionModel; Type enumType = importEnumForm.SelectedEnum; FlagsAttribute fa = enumType.GetCustomAttributes(false) .Where(a => a is FlagsAttribute) .SingleOrDefault() as FlagsAttribute; EnumeratedType enumeratedType = new EnumeratedType(diagram.Store); enumeratedType.CodeGenOptions = TypeDefinitionCodeGenOptions.None; enumeratedType.Name = enumType.Name; enumeratedType.Namespace = enumType.Namespace; enumeratedType.IsFlags = fa != null; FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); foreach (FieldInfo field in fields) { EnumerationLiteral enumeratedLiteral = new EnumerationLiteral(diagram.Store); enumeratedLiteral.Name = field.Name; enumeratedType.Literals.Add(enumeratedLiteral); } model.TypeDefinitions.Add(enumeratedType); transaction.Commit(); } else { transaction.Rollback(); } } } } }
private void GenerateValidators(ConfigurationSectionModel model, CodeCompileUnit generationUnit) { bool hasCallback = false; foreach (PropertyValidator validator in model.PropertyValidators.Validators) { if (validator is CallbackValidator) { hasCallback = true; break; } } if (hasCallback) { // Create the namespace block CodeNamespace callbackValidatorNamespace = new CodeNamespace(model.Namespace); generationUnit.Namespaces.Add(callbackValidatorNamespace); foreach (PropertyValidator validator in model.PropertyValidators.Validators) { CallbackValidator callbackValidator = validator as CallbackValidator; if (callbackValidator == null) { continue; } string callbackClassName = string.Format("{0}CallbackValidatorClass", callbackValidator.Name); string callbackMethodName = string.Format("{0}Callback", callbackValidator.Callback); string FQ = string.Format("{0}.{1}", model.Namespace, callbackClassName); CodeTypeDeclaration validationCallbackClass = new CodeTypeDeclaration(callbackClassName); callbackValidatorNamespace.Types.Add(validationCallbackClass); validationCallbackClass.Comments.Add(DocComment("<summary>")); validationCallbackClass.Comments.Add(DocComment(string.Format("Class for the {0} callback validator", callbackValidator.Name))); validationCallbackClass.Comments.Add(DocComment("</summary>")); validationCallbackClass.Attributes = MemberAttributes.Public; validationCallbackClass.IsPartial = true; validationCallbackClass.IsClass = true; // Generate callback method CodeMemberMethod callbackCallbackMethod = new CodeMemberMethod(); callbackCallbackMethod.Comments.Add(DocComment("<summary>")); callbackCallbackMethod.Comments.Add(DocComment(string.Format("Validation callback for the {0} callback validator", callbackValidator.Name))); callbackCallbackMethod.Comments.Add(DocComment("</summary>")); callbackCallbackMethod.Comments.Add(DocComment("<param name=\"value\">The value to validate.</param>")); callbackCallbackMethod.Comments.Add(DocComment(string.Format("<exception cref=\"{0}\">The value was not valid.</exception>", GetTypeReferenceString(typeof(System.ArgumentException))))); callbackCallbackMethod.CustomAttributes.Add(_generatedCodeAttribute); callbackCallbackMethod.Attributes = MemberAttributes.Public | MemberAttributes.Static | MemberAttributes.Final; callbackCallbackMethod.ReturnType = _void; callbackCallbackMethod.Name = callbackMethodName; callbackCallbackMethod.Parameters.Add(new CodeParameterDeclarationExpression(_object, "value")); callbackCallbackMethod.Statements.Add(Comment("IMPORTANT NOTE: The code below does not build by default.")); callbackCallbackMethod.Statements.Add(Comment("You have placed a callback validator on this property.")); callbackCallbackMethod.Statements.Add(Comment("Copy the commented code below to a separate file and ")); callbackCallbackMethod.Statements.Add(Comment("implement the method.")); callbackCallbackMethod.Statements.Add(Comment("")); // Generate a partial class with a callback method, then put that // generated code into the comments for the callback // method as an instruction to the user on how to handle the callback. { CodeTypeDeclaration partialElementDeclaration = new CodeTypeDeclaration(validationCallbackClass.Name); partialElementDeclaration.Attributes = MemberAttributes.Public; partialElementDeclaration.IsPartial = true; partialElementDeclaration.IsClass = true; CodeMemberMethod callbackMethod = new CodeMemberMethod(); partialElementDeclaration.Members.Add(callbackMethod); callbackMethod.Attributes = callbackCallbackMethod.Attributes; callbackMethod.ReturnType = _void; callbackMethod.Name = callbackValidator.Callback; callbackMethod.Parameters.Add(new CodeParameterDeclarationExpression(_object, "value")); // Throw NotImplementedException as per what is normal in generated methods that // are intended to be filled. callbackMethod.Statements.Add( new CodeThrowExceptionStatement( new CodeObjectCreateExpression( GlobalReference(typeof(NotImplementedException)) ) ) ); // Convert to string and place in comments string generatedCode = CodeTypeDeclarationToString(partialElementDeclaration); foreach (string line in generatedCode.Split(new string[] { "\r\n" }, int.MaxValue, StringSplitOptions.None)) { callbackCallbackMethod.Statements.Add(Comment(line)); } callbackCallbackMethod.Statements.Add( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(GlobalSelfReference(FQ)), callbackValidator.Callback, new CodeArgumentReferenceExpression("value") ) ); } validationCallbackClass.Members.Add(callbackCallbackMethod); } } }