/// <summary> /// Writes an implementation of the <see cref="IDataSourceWrapper"/> interface. /// </summary> /// <param name="dataSourceWrapperInfo">A <see cref="DataSourceWrapperInfo"/> describing the data source wrapper for which to write an <see cref="IDataSourceWrapper"/> implementation.</param> public void WriteIDataSourceWrapperImplementation(DataSourceWrapperInfo dataSourceWrapperInfo) { WriteLine("public override Object WrappedDataSource"); WriteLine("{"); WriteLine("get { return dataSource; }"); WriteLine("}"); WriteLine("private readonly {0} dataSource;", GetCSharpTypeName(dataSourceWrapperInfo.DataSourceType)); }
/// <summary> /// Writes a constructor for the specified data source wrapper. /// </summary> /// <param name="dataSourceWrapperInfo">A <see cref="DataSourceWrapperInfo"/> describing the data source for which to write a constructor.</param> public void WriteConstructor(DataSourceWrapperInfo dataSourceWrapperInfo) { WriteLine("public {0}({1} dataSource, {2} namescope) : base(namescope)", dataSourceWrapperInfo.DataSourceWrapperName, GetCSharpTypeName(dataSourceWrapperInfo.DataSourceType), GetCSharpTypeName(typeof(Namescope))); WriteLine("{"); WriteLine("this.dataSource = dataSource;"); WriteLine("}"); }
/// <summary> /// Given a targeted binding expression (in the form "foo->bar"), this method extracts the target name, target type, and expression text. /// </summary> private Boolean GetExpressionTargetInfo(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo, XObject source, ref String expText, out String expTarget, out Type expTargetType) { const string TargetExpressionDelimiter = "->"; var expOriginal = expText; var delimiterIndex = expText.IndexOf(TargetExpressionDelimiter); if (delimiterIndex >= 0) { var expPartTarget = expText.Substring(0, delimiterIndex); var expPartText = expText.Substring(delimiterIndex + TargetExpressionDelimiter.Length); var matchCandidates = (from element in dataSourceWrapperInfo.DataSourceDefinition.Definition.Descendants() where (String)element.Attribute("Name") == expPartTarget select element).ToList(); if (matchCandidates.Count == 0) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsNotFound.Format(expPartTarget)); } if (matchCandidates.Count > 1) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsAmbiguous.Format(expPartTarget)); } var match = matchCandidates.Single(); var matchName = match.Name.LocalName; expText = expPartText; expTargetType = ExpressionCompiler.GetPlaceholderType(dataSourceWrapperInfo.DataSourceType, matchName); if (expTargetType == null && !state.GetKnownType(matchName, out expTargetType)) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsUnrecognizedType.Format(expOriginal, matchName)); } expTarget = String.Format("__UPF_GetElementByName<{0}>(\"{1}\").", GetCSharpTypeName(expTargetType), expPartTarget); return(true); } expTarget = default(String); expTargetType = dataSourceWrapperInfo.DataSourceType; return(false); }
/// <summary> /// Writes a property which wraps a binding expression. /// </summary> /// <param name="state">The expression compiler's current state.</param> /// <param name="dataSourceWrapperInfo">A <see cref="DataSourceWrapperInfo"/> describing the data source for which to write an expression property.</param> /// <param name="expressionInfo">The binding expression for which to write a property.</param> /// <param name="id">The expression's identifier within the view model.</param> public void WriteExpressionProperty(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo, BindingExpressionInfo expressionInfo, Int32 id) { var isDependencyProperty = false; var isSimpleDependencyProperty = false; var expText = BindingExpressions.GetBindingMemberPathPart(expressionInfo.Expression); var expTarget = default(String); var expTargetType = dataSourceWrapperInfo.DataSourceType; var expFormatString = BindingExpressions.GetBindingFormatStringPart(expressionInfo.Expression); var targeted = GetExpressionTargetInfo(state, dataSourceWrapperInfo, expressionInfo.Source, ref expText, out expTarget, out expTargetType); var dprop = DependencyProperty.FindByName(expText, expTargetType); var dpropField = default(FieldInfo); if (dprop != null) { isDependencyProperty = true; dpropField = (from prop in dprop.OwnerType.GetFields(BindingFlags.Public | BindingFlags.Static) where prop.FieldType == typeof(DependencyProperty) && prop.GetValue(null) == dprop select prop).SingleOrDefault(); if (dpropField == null) { throw new BindingExpressionCompilationErrorException(expressionInfo.Source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, PresentationStrings.CannotFindDependencyPropertyField.Format(dprop.OwnerType.Name, dprop.Name)); } if (String.IsNullOrEmpty(expFormatString) && !targeted) { isSimpleDependencyProperty = true; } } WriteLine("[{0}(@\"{1}\", SimpleDependencyPropertyOwner = {2}, SimpleDependencyPropertyName = {3})]", typeof(CompiledBindingExpressionAttribute).FullName, expressionInfo.Expression.Replace("\"", "\"\""), isSimpleDependencyProperty ? "typeof(" + GetCSharpTypeName(dprop.OwnerType) + ")" : "null", isSimpleDependencyProperty ? "\"" + dprop.Name + "\"" : "null"); WriteLine("public {0} __UPF_Expression{1}", GetCSharpTypeName(expressionInfo.Type), id); WriteLine("{"); if (expressionInfo.GenerateGetter) { expressionInfo.GetterLineStart = LineCount; var getexp = default(String); if (isDependencyProperty) { getexp = String.Format("{0}GetValue<{1}>({2}.{3})", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name); } else { getexp = String.Format("{0}{1}", expTarget, expText); } var hasFormatString = !String.IsNullOrEmpty(expFormatString); expFormatString = hasFormatString ? String.Format("\"{{0:{0}}}\"", expFormatString) : "null"; if (IsStringType(expressionInfo.Type) || (expressionInfo.Type == typeof(Object) && hasFormatString)) { WriteLine("get"); WriteLine("{"); WriteLine("var value = {0};", getexp); WriteLine("return ({0})__UPF_ConvertToString(value, {1});", GetCSharpTypeName(expressionInfo.Type), expFormatString); WriteLine("}"); } else { WriteLine("get {{ return ({0})({1}); }}", GetCSharpTypeName(expressionInfo.Type), getexp); } expressionInfo.GetterLineEnd = LineCount - 1; } if (dprop != null && dprop.IsReadOnly) { expressionInfo.GenerateSetter = false; } if (expressionInfo.GenerateSetter) { var targetTypeName = expressionInfo.CS0266TargetType; var targetTypeSpecified = !String.IsNullOrEmpty(targetTypeName); expressionInfo.SetterLineStart = LineCount; if (isDependencyProperty) { if (IsStringType(expressionInfo.Type)) { WriteLine("set"); WriteLine("{"); WriteLine("var current = {0}GetValue<{1}>({2}.{3});", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name); WriteLine("{0}SetValue<{1}>({2}.{3}, __UPF_ConvertFromString(value.ToString(), current));", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name); WriteLine("}"); } else { if (expressionInfo.NullableFixup) { WriteLine(targetTypeSpecified ? "set {{ {0}SetValue<{1}>({2}.{3}, ({4})(value ?? default({1}))); }}" : "set {{ {0}SetValue<{1}>({2}.{3}, value ?? default({1})); }}", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name, targetTypeName); } else { WriteLine(targetTypeSpecified ? "set {{ {0}SetValue<{1}>({2}.{3}, ({4})(value)); }}" : "set {{ {0}SetValue<{1}>({2}.{3}, value); }}", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name, targetTypeName); } } } else { if (expressionInfo.Type == typeof(String) || expressionInfo.Type == typeof(VersionedStringSource)) { WriteLine("set"); WriteLine("{"); WriteLine("var current = {0}{1};", expTarget, expText); WriteLine("{0}{1} = __UPF_ConvertFromString(value.ToString(), current);", expTarget, expText); WriteLine("}"); } else { if (expressionInfo.NullableFixup) { WriteLine(targetTypeSpecified ? "set {{ {0}{1} = ({3})(value ?? default({2})); }}" : "set {{ {0}{1} = value ?? default({2}); }}", expTarget, expText, GetCSharpTypeName(Nullable.GetUnderlyingType(expressionInfo.Type)), targetTypeName); } else { WriteLine(targetTypeSpecified ? "set {{ {0}{1} = ({2})(value); }}" : "set {{ {0}{1} = value; }}", expTarget, expText, targetTypeName); } } } expressionInfo.SetterLineEnd = LineCount - 1; } WriteLine("}"); }
/// <summary> /// Gets the name of the file in which the specified data source wrapper's source code is saved during compilation. /// </summary> private static String GetWorkingFileForDataSourceWrapper(DataSourceWrapperInfo dataSourceWrapperInfo) { var path = Path.ChangeExtension(Path.Combine(Path.GetTempPath(), dataSourceWrapperInfo.UniqueID.ToString()), "cs"); return path; }
/// <summary> /// Given a targeted binding expression (in the form "foo->bar"), this method extracts the target name, target type, and expression text. /// </summary> private Boolean GetExpressionTargetInfo(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo, XObject source, ref String expText, out String expTarget, out Type expTargetType) { const string TargetExpressionDelimiter = "->"; var expOriginal = expText; var delimiterIndex = expText.IndexOf(TargetExpressionDelimiter); if (delimiterIndex >= 0) { var expPartTarget = expText.Substring(0, delimiterIndex); var expPartText = expText.Substring(delimiterIndex + TargetExpressionDelimiter.Length); var matchCandidates = (from element in dataSourceWrapperInfo.DataSourceDefinition.Definition.Descendants() where (String)element.Attribute("Name") == expPartTarget select element).ToList(); if (matchCandidates.Count == 0) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsNotFound.Format(expPartTarget)); } if (matchCandidates.Count > 1) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsAmbiguous.Format(expPartTarget)); } var match = matchCandidates.Single(); var matchName = match.Name.LocalName; expText = expPartText; expTargetType = ExpressionCompiler.GetPlaceholderType(dataSourceWrapperInfo.DataSourceType, matchName); if (expTargetType == null && !state.GetKnownType(matchName, out expTargetType)) { throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, CompilerStrings.ExpressionTargetIsUnrecognizedType.Format(expOriginal, matchName)); } expTarget = String.Format("__UPF_GetElementByName<{0}>(\"{1}\").", GetCSharpTypeName(expTargetType), expPartTarget); return true; } expTarget = default(String); expTargetType = dataSourceWrapperInfo.DataSourceType; return false; }
/// <summary> /// Writes the source code for the specified data source wrapper. /// </summary> /// <param name="state">The expression compiler's current state.</param> /// <param name="dataSourceWrapperInfo">The <see cref="DataSourceWrapperInfo"/> that describes the data source wrapper being generated.</param> private static void WriteSourceCodeForDataSourceWrapper(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo) { using (var writer = new DataSourceWrapperWriter()) { // Using statements var imports = Enumerable.Union(new[] { "System" }, dataSourceWrapperInfo.Imports).Distinct().OrderBy(x => x); foreach (var import in imports) { writer.WriteLine("using {0};", import); } writer.WriteLine(); // Namespace and class declaration var @namespace = dataSourceWrapperInfo.DataSourceDefinition.DataSourceWrapperNamespace; writer.WriteLine("namespace " + @namespace); writer.WriteLine("{"); writer.WriteLine("#pragma warning disable 1591"); writer.WriteLine("#pragma warning disable 0184"); writer.WriteLine("[System.CLSCompliant(false)]"); writer.WriteLine("[System.CodeDom.Compiler.GeneratedCode(\"UPF Binding Expression Compiler\", \"{0}\")]", FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion); writer.WriteLine("public sealed partial class {0} : {1}", dataSourceWrapperInfo.DataSourceWrapperName, writer.GetCSharpTypeName(typeof(CompiledDataSourceWrapper))); writer.WriteLine("{"); // Constructors writer.WriteLine("#region Constructors"); writer.WriteConstructor(dataSourceWrapperInfo); writer.WriteLine("#endregion"); writer.WriteLine(); // IDataSourceWrapper writer.WriteLine("#region IDataSourceWrapper"); writer.WriteIDataSourceWrapperImplementation(dataSourceWrapperInfo); writer.WriteLine("#endregion"); writer.WriteLine(); // Methods writer.WriteLine("#region Methods"); var methods = dataSourceWrapperInfo.DataSourceType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (var method in methods) { if (!NeedsWrapper(method)) continue; writer.WriteWrapperMethod(method); } writer.WriteLine("#endregion"); writer.WriteLine(); // Properties writer.WriteLine("#region Properties"); var properties = dataSourceWrapperInfo.DataSourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (var property in properties) { if (!NeedsWrapper(property)) continue; writer.WriteWrapperProperty(property); } writer.WriteLine("#endregion"); writer.WriteLine(); // Fields writer.WriteLine("#region Fields"); var fields = dataSourceWrapperInfo.DataSourceType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (var field in fields) { if (!NeedsWrapper(field)) continue; writer.WriteWrapperProperty(field); } writer.WriteLine("#endregion"); writer.WriteLine(); // Expressions writer.WriteLine("#region Expressions"); for (int i = 0; i < dataSourceWrapperInfo.Expressions.Count; i++) { var expressionInfo = dataSourceWrapperInfo.Expressions[i]; writer.WriteExpressionProperty(state, dataSourceWrapperInfo, expressionInfo, i); } writer.WriteLine("#endregion"); // Source code generation complete writer.WriteLine("}"); writer.WriteLine("#pragma warning restore 0184"); writer.WriteLine("#pragma warning restore 1591"); writer.WriteLine("}"); dataSourceWrapperInfo.DataSourceWrapperSourceCode = writer.ToString(); } }
/// <summary> /// Writes an implementation of the <see cref="IDataSourceWrapper"/> interface. /// </summary> /// <param name="dataSourceWrapperInfo">A <see cref="DataSourceWrapperInfo"/> describing the data source wrapper for which to write an <see cref="IDataSourceWrapper"/> implementation.</param> public void WriteIDataSourceWrapperImplementation(DataSourceWrapperInfo dataSourceWrapperInfo) { WriteLine("public override Object WrappedDataSource"); WriteLine("{"); WriteLine("get { return value; }"); WriteLine("}"); WriteLine("private readonly {0} value;", GetCSharpTypeName(dataSourceWrapperInfo.DataSourceType)); }
/// <summary> /// Writes a property which wraps a binding expression. /// </summary> /// <param name="state">The expression compiler's current state.</param> /// <param name="dataSourceWrapperInfo">A <see cref="DataSourceWrapperInfo"/> describing the data source for which to write an expression property.</param> /// <param name="expressionInfo">The binding expression for which to write a property.</param> /// <param name="id">The expression's identifier within the view model.</param> public void WriteExpressionProperty(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo, BindingExpressionInfo expressionInfo, Int32 id) { var isDependencyProperty = false; var isSimpleDependencyProperty = false; var expText = BindingExpressions.GetBindingMemberPathPart(expressionInfo.Expression); var expTarget = default(String); var expTargetType = dataSourceWrapperInfo.DataSourceType; var expFormatString = BindingExpressions.GetBindingFormatStringPart(expressionInfo.Expression); var targeted = GetExpressionTargetInfo(state, dataSourceWrapperInfo, expressionInfo.Source, ref expText, out expTarget, out expTargetType); var dprop = DependencyProperty.FindByName(expText, expTargetType); var dpropField = default(FieldInfo); if (dprop != null) { isDependencyProperty = true; dpropField = (from prop in dprop.OwnerType.GetFields(BindingFlags.Public | BindingFlags.Static) where prop.FieldType == typeof(DependencyProperty) && prop.GetValue(null) == dprop select prop).SingleOrDefault(); if (dpropField == null) { throw new BindingExpressionCompilationErrorException(expressionInfo.Source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath, PresentationStrings.CannotFindDependencyPropertyField.Format(dprop.OwnerType.Name, dprop.Name)); } if (String.IsNullOrEmpty(expFormatString) && !targeted) { isSimpleDependencyProperty = true; } } WriteLine("[{0}(@\"{1}\", SimpleDependencyPropertyOwner = {2}, SimpleDependencyPropertyName = {3})]", typeof(CompiledBindingExpressionAttribute).FullName, expressionInfo.Expression.Replace("\"", "\"\""), isSimpleDependencyProperty ? "typeof(" + GetCSharpTypeName(dprop.OwnerType) + ")" : "null", isSimpleDependencyProperty ? "\"" + dprop.Name + "\"" : "null"); WriteLine("public {0} __UPF_Expression{1}", GetCSharpTypeName(expressionInfo.Type), id); WriteLine("{"); if (expressionInfo.GenerateGetter) { expressionInfo.GetterLineStart = LineCount; var getexp = default(String); if (isDependencyProperty) { getexp = String.Format("{0}GetValue<{1}>({2}.{3})", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name); } else { getexp = String.Format("{0}{1}", expTarget, expText); } var hasFormatString = !String.IsNullOrEmpty(expFormatString); expFormatString = hasFormatString ? String.Format("\"{{0:{0}}}\"", expFormatString) : "null"; if (IsStringType(expressionInfo.Type) || (expressionInfo.Type == typeof(Object) && hasFormatString)) { WriteLine("get"); WriteLine("{"); WriteLine("var value = {0};", getexp); WriteLine("return ({0})__UPF_ConvertToString(value, {1});", GetCSharpTypeName(expressionInfo.Type), expFormatString); WriteLine("}"); } else { WriteLine("get {{ return ({0})({1}); }}", GetCSharpTypeName(expressionInfo.Type), getexp); } expressionInfo.GetterLineEnd = LineCount - 1; } if (dprop != null && dprop.IsReadOnly) expressionInfo.GenerateSetter = false; if (expressionInfo.GenerateSetter) { var targetTypeName = expressionInfo.CS0266TargetType; var targetTypeSpecified = !String.IsNullOrEmpty(targetTypeName); expressionInfo.SetterLineStart = LineCount; if (isDependencyProperty) { if (IsStringType(expressionInfo.Type)) { WriteLine("set"); WriteLine("{"); WriteLine("var current = {0}GetValue<{1}>({2}.{3});", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name); WriteLine("{0}SetValue<{1}>({2}.{3}, __UPF_ConvertFromString(value, current));", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name); WriteLine("}"); } else { if (expressionInfo.NullableFixup) { WriteLine(targetTypeSpecified ? "set {{ {0}SetValue<{1}>({2}.{3}, ({4})(value ?? default({1}))); }}" : "set {{ {0}SetValue<{1}>({2}.{3}, value ?? default({1})); }}", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name, targetTypeName); } else { WriteLine(targetTypeSpecified ? "set {{ {0}SetValue<{1}>({2}.{3}, ({4})(value)); }}" : "set {{ {0}SetValue<{1}>({2}.{3}, value); }}", expTarget, GetCSharpTypeName(dprop.PropertyType), GetCSharpTypeName(dprop.OwnerType), dpropField.Name, targetTypeName); } } } else { if (IsStringType(expressionInfo.Type)) { WriteLine("set"); WriteLine("{"); WriteLine("var current = {0}{1};", expTarget, expText); WriteLine("{0}{1} = __UPF_ConvertFromString(value, current);", expTarget, expText); WriteLine("}"); } else { if (expressionInfo.NullableFixup) { WriteLine(targetTypeSpecified ? "set {{ {0}{1} = ({3})(value ?? default({2})); }}" : "set {{ {0}{1} = value ?? default({2}); }}", expTarget, expText, GetCSharpTypeName(Nullable.GetUnderlyingType(expressionInfo.Type)), targetTypeName); } else { WriteLine(targetTypeSpecified ? "set {{ {0}{1} = ({2})(value); }}" : "set {{ {0}{1} = value; }}", expTarget, expText, targetTypeName); } } } expressionInfo.SetterLineEnd = LineCount - 1; } WriteLine("}"); }
/// <summary> /// Writes a constructor for the specified data source wrapper. /// </summary> /// <param name="dataSourceWrapperInfo">A <see cref="DataSourceWrapperInfo"/> describing the data source for which to write a constructor.</param> public void WriteConstructor(DataSourceWrapperInfo dataSourceWrapperInfo) { WriteLine("public {0}({1} dataSource, {2} namescope) : base(namescope)", dataSourceWrapperInfo.DataSourceWrapperName, GetCSharpTypeName(dataSourceWrapperInfo.DataSourceType), GetCSharpTypeName(typeof(Namescope))); WriteLine("{"); WriteLine("this.value = dataSource;"); WriteLine("}"); }
/// <summary> /// Writes the source code for an individual data source wrapper class. /// </summary> private static void WriteSourceCodeForDataSourceWrapperClass(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo, DataSourceWrapperWriter writer) { // Class declaration writer.WriteLine("[System.CLSCompliant(false)]"); writer.WriteLine("[System.CodeDom.Compiler.GeneratedCode(\"UPF Binding Expression Compiler\", \"{0}\")]", FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion); writer.WriteLine("public sealed partial class {0} : {1}", dataSourceWrapperInfo.DataSourceWrapperName, writer.GetCSharpTypeName(typeof(CompiledDataSourceWrapper))); writer.WriteLine("{"); // Constructors writer.WriteLine("#region Constructors"); writer.WriteConstructor(dataSourceWrapperInfo); writer.WriteLine("#endregion"); writer.WriteLine(); // IDataSourceWrapper writer.WriteLine("#region IDataSourceWrapper"); writer.WriteIDataSourceWrapperImplementation(dataSourceWrapperInfo); writer.WriteLine("#endregion"); writer.WriteLine(); // Methods writer.WriteLine("#region Methods"); var methods = dataSourceWrapperInfo.DataSourceType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (var method in methods) { if (!NeedsWrapper(method)) continue; writer.WriteWrapperMethod(method); } writer.WriteLine("#endregion"); writer.WriteLine(); // Properties writer.WriteLine("#region Properties"); var properties = dataSourceWrapperInfo.DataSourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (var property in properties) { if (!NeedsWrapper(property)) continue; writer.WriteWrapperProperty(property); } writer.WriteLine("#endregion"); writer.WriteLine(); // Fields writer.WriteLine("#region Fields"); var fields = dataSourceWrapperInfo.DataSourceType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (var field in fields) { if (!NeedsWrapper(field)) continue; writer.WriteWrapperProperty(field); } writer.WriteLine("#endregion"); writer.WriteLine(); // Expressions writer.WriteLine("#region Expressions"); for (int i = 0; i < dataSourceWrapperInfo.Expressions.Count; i++) { var expressionInfo = dataSourceWrapperInfo.Expressions[i]; writer.WriteExpressionProperty(state, dataSourceWrapperInfo, expressionInfo, i); } writer.WriteLine("#endregion"); // Class complete writer.WriteLine("}"); }
/// <summary> /// Writes the source code for the specified data source wrapper. /// </summary> private static void WriteSourceCodeForDataSourceWrapper(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo) { using (var writer = new DataSourceWrapperWriter()) { // Using statements var imports = Enumerable.Union(new[] { "System" }, dataSourceWrapperInfo.Imports).Distinct().OrderBy(x => x); foreach (var import in imports) { writer.WriteLine("using {0};", import); } writer.WriteLine(); // Namespace declaration var @namespace = dataSourceWrapperInfo.DataSourceDefinition.DataSourceWrapperNamespace; writer.WriteLine("namespace " + @namespace); writer.WriteLine("{"); writer.WriteLine("#pragma warning disable 1591"); writer.WriteLine("#pragma warning disable 0184"); // Data source wrapper class - main WriteSourceCodeForDataSourceWrapperClass(state, dataSourceWrapperInfo, writer); // Data source wrapper class - dependent foreach (var dependentWrapperInfo in dataSourceWrapperInfo.DependentWrapperInfos) WriteSourceCodeForDataSourceWrapperClass(state, dependentWrapperInfo, writer); // Namespace complete writer.WriteLine("#pragma warning restore 0184"); writer.WriteLine("#pragma warning restore 1591"); writer.WriteLine("}"); dataSourceWrapperInfo.DataSourceWrapperSourceCode = writer.ToString(); } }