public void FinalizeAndAddToAssembly() { if (IsFinalized) { LogHelper.Context.Log.WarnFormat("The dynamic class '{0}.{1}' was already to dynamic assembly.", ClassNamespace, ClassName); return; } IsFinalized = true; foreach (var inProgressFunctionData in _inProgressConstructorsData) { _sharpCode.Append(inProgressFunctionData.GetCode()); _sharpCode.AppendLine(); } foreach (var inProgressFunctionData in _inProgressMethodsData) { _sharpCode.Append(inProgressFunctionData.GetCode()); _sharpCode.AppendLine(); } _sharpCode.AppendLine("}"); _sharpCode.AppendLine("}"); StringBuilder sharpCodeWithUsingStamentes; if (_usingStatments.Count > 0) { sharpCodeWithUsingStamentes = new StringBuilder(); foreach (var referencedNamespace in _usingStatments) { sharpCodeWithUsingStamentes.AppendLine($"using {referencedNamespace};"); } sharpCodeWithUsingStamentes.Append(_sharpCode); } else { sharpCodeWithUsingStamentes = _sharpCode; } _dynamicAssemblyBuilder.AddCSharpFile(sharpCodeWithUsingStamentes.ToString()); }
public override void GenerateAutoImplementedServiceClassCSharp(IDynamicAssemblyBuilder dynamicAssemblyBuilder, string dynamicImplementationsNamespace, out string generatedClassFullName) { // Add assemblies referenced by service var className = $"{ImplementedInterfaceTypeInfo.Type.Name}_{GlobalsCoreAmbientContext.Context.GenerateUniqueId()}"; generatedClassFullName = $"{dynamicImplementationsNamespace}.{className}"; var classStrBldr = new StringBuilder(5000); var classMemberVariablesStrBldr = new StringBuilder(1000); classStrBldr.AppendLine(); classStrBldr.AppendLine("using System;"); classStrBldr.AppendLine($"namespace {dynamicImplementationsNamespace}"); classStrBldr.AppendLine("{"); classStrBldr.AppendLine($"public sealed class {className}: {ImplementedInterfaceTypeInfo.TypeCSharpFullName}"); classStrBldr.AppendLine("{"); void ProcessType(Type type, ref bool stopProcessingParam) { foreach (var methodInfo in type.GetMethods()) { if ((methodInfo.Attributes & MethodAttributes.SpecialName) > 0) { continue; } var methodSignature = GetMethodSignature(methodInfo); classStrBldr.Append(methodSignature); if (_methodInfoToSimilarOrSameAutoGeneratedServiceMethodElementMap.TryGetValue(methodInfo, out var autoGeneratedServiceMethodElement)) { if (autoGeneratedServiceMethodElement.ImplementedMehodInfo == methodInfo) { AddMethodBodyForImplementedMethod(dynamicAssemblyBuilder, autoGeneratedServiceMethodElement, classStrBldr, classMemberVariablesStrBldr); } else { AddMethodBodyForNonImplementedMethodWithSimilarImplementedMethod(dynamicAssemblyBuilder, methodInfo, autoGeneratedServiceMethodElement, classStrBldr); } } else { classStrBldr.AppendLine("{"); foreach (var outParameterInfo in methodInfo.GetParameters().Where(x => x.IsOut)) { classStrBldr.AppendLine($"{outParameterInfo.Name}=default({outParameterInfo.ParameterType.GetTypeNameInCSharpClass()});"); } if (methodInfo.ReturnType != typeof(void)) { classStrBldr.Append($"return default({methodInfo.ReturnType.GetTypeNameInCSharpClass()});"); classStrBldr.AppendLine(); } classStrBldr.AppendLine("}"); } classStrBldr.AppendLine(); } foreach (var propertyInfo in type.GetProperties()) { var propertyHeader = GetPropertyHeader(propertyInfo); void AddGetSet() { classStrBldr.Append(" { get;"); if (propertyInfo.SetMethod != null) { classStrBldr.Append(" set;"); } classStrBldr.Append("}"); } classStrBldr.Append(propertyHeader); if (_propertyInfoToSimilarOrSameAutoGeneratedServicePropertyElementMap.TryGetValue(propertyInfo, out var similarOrSameAutoGeneratedServicePropertyElement)) { var similarPropertyInfo = similarOrSameAutoGeneratedServicePropertyElement.ImplementedPropertyInfo; if (similarPropertyInfo == propertyInfo) { AddGetSet(); classStrBldr.AppendLine($"={similarOrSameAutoGeneratedServicePropertyElement.ReturnValueElement.GenerateValueCSharp(dynamicAssemblyBuilder)};"); } else { var privateVariableName = $"_{propertyInfo.DeclaringType.Name}_{propertyInfo.Name}_{GlobalsCoreAmbientContext.Context.GenerateUniqueId()}"; // Not, for nullable values and reference types, we can check for null, to set if the value was initialized. // however, to make it simple, and also to avoid calling the other class property every time, in case the other property // value is null, lets use the valueWasSet variable for all cases. var valueWasSetVariableName = $"{privateVariableName}_ValueWasSet"; classStrBldr.AppendLine(); classStrBldr.AppendLine("{"); classStrBldr.AppendLine("get"); classStrBldr.AppendLine("{"); classStrBldr.AppendLine($"if ({valueWasSetVariableName}) return {privateVariableName};"); classStrBldr.Append($"{privateVariableName}=(({similarPropertyInfo.DeclaringType.GetTypeNameInCSharpClass()})this)"); classStrBldr.AppendLine($".{similarPropertyInfo.Name};"); classStrBldr.AppendLine($"{valueWasSetVariableName}=true;"); classStrBldr.AppendLine($"return {privateVariableName};"); classStrBldr.AppendLine("}"); if (propertyInfo.SetMethod != null) { classStrBldr.AppendLine("set"); classStrBldr.AppendLine("{"); classStrBldr.AppendLine($"{privateVariableName}=value;"); classStrBldr.AppendLine($"{valueWasSetVariableName}=true;"); classStrBldr.AppendLine("}"); } classStrBldr.AppendLine("}"); classStrBldr.AppendLine($"private bool {valueWasSetVariableName};"); classStrBldr.AppendLine($"private {propertyInfo.PropertyType.GetTypeNameInCSharpClass()} {privateVariableName};"); } } else { AddGetSet(); classStrBldr.AppendLine(); } } } var stopProcessing = false; TypeMemberLookupHelper.ProcessTypeImplementedInterfacesAndBaseTypes(ImplementedInterfaceTypeInfo.Type, ProcessType, ref stopProcessing); classStrBldr.Append(classMemberVariablesStrBldr); // Close class classStrBldr.AppendLine("}"); // Close namespace classStrBldr.AppendLine("}"); dynamicAssemblyBuilder.AddCSharpFile(classStrBldr.ToString()); }