AddToList template

This commit is contained in:
CodeLiturgy 2022-09-08 04:16:31 +01:00
parent dc23c79797
commit 15a0f1a4f4
13 changed files with 534 additions and 90 deletions

View File

@ -0,0 +1,43 @@
using BlueWest.EfMethods.Sources;
using static BlueWest.EfMethods.Sources.Constants;
namespace BlueWest.EfMethods.EfMethods.AttributeSources
{
public static class EfAddToListAttributeSource
{
internal const string AttributeName = "EfAddToList";
internal const string AttributeClassName = AttributeName + "Attribute";
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
internal static SourceCode Generate(SourceGenerationOptions options)
{
using var builder = new SourceBuilder()
.WriteLine(GeneratedFilesHeader)
.WriteLine("using System;")
.WriteLine()
.WriteLine($"namespace {RootNamespace}")
.WriteOpeningBracket();
builder
.WriteLine("/// <summary>")
.WriteLine("/// Attribute for generating a function to get many entities.")
.WriteLine("/// </summary>");
builder
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]")
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
.WriteOpeningBracket();
builder
.WriteLine($"public {AttributeName}Attribute(string listPropertyNameof, Type createType, Type returnType, string primaryKeyNameof){"{}"}")
.WriteLine();
builder
.WriteClosingBracket() // class
.WriteClosingBracket(); // namespace
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
}
}
}

View File

@ -0,0 +1,44 @@
using BlueWest.EfMethods;
using BlueWest.EfMethods.Sources;
using static BlueWest.EfMethods.Sources.Constants;
namespace BlueWest.Sources
{
public class EfGetListAttributeSource
{
internal const string AttributeName = "EfGetList";
internal const string AttributeClassName = AttributeName + "Attribute";
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
internal static SourceCode Generate(SourceGenerationOptions options)
{
using var builder = new SourceBuilder()
.WriteLine(GeneratedFilesHeader)
.WriteLine("using System;")
.WriteLine()
.WriteLine($"namespace {RootNamespace}")
.WriteOpeningBracket();
builder
.WriteLine("/// <summary>")
.WriteLine("/// Attribute for generating a function to get many entities.")
.WriteLine("/// </summary>");
builder
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]")
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
.WriteOpeningBracket();
builder
.WriteLine($"public {AttributeName}Attribute(string listPropertyNameof, Type returnType, string primaryKeyNameof){"{}"}")
.WriteLine();
builder
.WriteClosingBracket() // class
.WriteClosingBracket(); // namespace
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
}
}
}

View File

@ -4,8 +4,10 @@ using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using BlueWest.EfMethods.EfMethods.AttributeSources;
using BlueWest.EfMethods.Extensions; using BlueWest.EfMethods.Extensions;
using BlueWest.EfMethods.Sources; using BlueWest.EfMethods.Sources;
using BlueWest.Sources;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
@ -113,14 +115,18 @@ namespace BlueWest.EfMethods
return new TypeInfo(); return new TypeInfo();
} }
protected TypeInfo? FindFirstTypeInfoOfMemberExpressionSyntax(SemanticModel semanticModel, SyntaxNode attributeSyntax) protected TypeInfo? FindTypeInfoOfMemberExpressionSyntax(SemanticModel semanticModel, SyntaxNode attributeSyntax, int skip = 0)
{ {
semanticModel ??= Compilation.GetSemanticModel(attributeSyntax.SyntaxTree); semanticModel ??= Compilation.GetSemanticModel(attributeSyntax.SyntaxTree);
var descendentNodes = attributeSyntax var descendentNodes = attributeSyntax
.DescendantNodes(); .DescendantNodes();
// Get the type of the key member id // Get the type of the key member id
var expression = descendentNodes.OfType<MemberAccessExpressionSyntax>().FirstOrDefault(); var expression = descendentNodes
.OfType<MemberAccessExpressionSyntax>()
.Skip(skip)
.FirstOrDefault();
if (expression != null) if (expression != null)
{ {
return semanticModel.GetTypeInfo(expression); return semanticModel.GetTypeInfo(expression);
@ -130,10 +136,10 @@ namespace BlueWest.EfMethods
} }
protected string ExtractNameOfMemberName(MemberDeclarationSyntax memberDeclarationSyntax, string attributeName, SemanticModel? semanticModel = null) protected string ExtractNameOfMemberName(MemberDeclarationSyntax memberDeclarationSyntax, string attributeName, SemanticModel? semanticModel = null, int skip = 0)
{ {
var attributeData = memberDeclarationSyntax.GetAttribute(attributeName); var attributeData = memberDeclarationSyntax.GetAttribute(attributeName);
var sourceSymbol = ExtractNameOfMemberName(attributeData, semanticModel); var sourceSymbol = ExtractNameOfMemberName(attributeData, semanticModel, skip);
return sourceSymbol; return sourceSymbol;
} }
@ -184,7 +190,7 @@ namespace BlueWest.EfMethods
return sourceTypeExpressionSyntax; return sourceTypeExpressionSyntax;
} }
protected string ExtractNameOfMemberName(SyntaxNode? attributeSyntax, SemanticModel semanticModel) protected string ExtractNameOfMemberName(SyntaxNode? attributeSyntax, SemanticModel semanticModel, int skip)
{ {
if (attributeSyntax is null) if (attributeSyntax is null)
{ {
@ -195,6 +201,7 @@ namespace BlueWest.EfMethods
.DescendantNodes(); .DescendantNodes();
var idNode = descendentNodes.OfType<InvocationExpressionSyntax>() var idNode = descendentNodes.OfType<InvocationExpressionSyntax>()
.Skip(skip)
.FirstOrDefault() .FirstOrDefault()
?.ChildNodesAndTokens() ?.ChildNodesAndTokens()
.FirstOrDefault(x => x.IsKind(SyntaxKind.ArgumentList)) .FirstOrDefault(x => x.IsKind(SyntaxKind.ArgumentList))
@ -262,17 +269,19 @@ namespace BlueWest.EfMethods
// handles different attributes // handles different attributes
var addAttributeSymbols = GetAllowedMemberSyntaxes(EfAddMethodsAttributeSource.AttributeName); var addMembers = GetAllowedMemberSyntaxes(EfAddMethodsAttributeSource.AttributeName);
var updateAttributesMembers = GetAllowedMemberSyntaxes(EfUpdateMethodsAttributeSource.AttributeName); var updateMembers = GetAllowedMemberSyntaxes(EfUpdateMethodsAttributeSource.AttributeName);
var getOneAttributesMembers = GetAllowedMemberSyntaxes(EfGetOneByAttributeSource.AttributeName); var getOneByMembers = GetAllowedMemberSyntaxes(EfGetOneByAttributeSource.AttributeName);
var getOneWithAttributesMembers = GetAllowedMemberSyntaxes(EfGetOneAttributeSource.AttributeName); var getOneMembers = GetAllowedMemberSyntaxes(EfGetOneAttributeSource.AttributeName);
var getManyWithAttributesMembers = GetAllowedMemberSyntaxes(EfGetManyAttributeSource.AttributeName); var efGetManyMembers = GetAllowedMemberSyntaxes(EfGetManyAttributeSource.AttributeName);
var getListMembers = GetAllowedMemberSyntaxes(EfGetListAttributeSource.AttributeName);
var getAddToListMembers = GetAllowedMemberSyntaxes(EfAddToListAttributeSource.AttributeName);
List<EfEntityDataModel> methodsModels = new List<EfEntityDataModel>(); List<EfEntityDataModel> methodsModels = new List<EfEntityDataModel>();
foreach (var uProperty in getOneAttributesMembers) foreach (var uProperty in getOneByMembers)
{ {
var entityDataModel = GetEntityData(uProperty, semanticModel); var entityDataModel = GetEntityData(uProperty, semanticModel);
var newUpdateModel = ExtractEfGetEntityByModel(uProperty, semanticModel, entityDataModel); var newUpdateModel = ExtractEfGetEntityByModel(uProperty, semanticModel, entityDataModel);
@ -280,14 +289,14 @@ namespace BlueWest.EfMethods
} }
foreach (var uProperty in addAttributeSymbols) foreach (var uProperty in addMembers)
{ {
var entityDataModel = GetEntityData(uProperty, semanticModel); var entityDataModel = GetEntityData(uProperty, semanticModel);
var newAddModel = ExtractEfAddMethodsModel(semanticModel, uProperty, entityDataModel); var newAddModel = ExtractEfAddMethodsModel(semanticModel, uProperty, entityDataModel);
methodsModels.Add(newAddModel); methodsModels.Add(newAddModel);
} }
foreach (var uProperty in updateAttributesMembers) foreach (var uProperty in updateMembers)
{ {
var entityDataModel = GetEntityData(uProperty, semanticModel); var entityDataModel = GetEntityData(uProperty, semanticModel);
var newUpdateModel = ExtractEfUpdateMethodsModel(uProperty, semanticModel, entityDataModel); var newUpdateModel = ExtractEfUpdateMethodsModel(uProperty, semanticModel, entityDataModel);
@ -295,7 +304,7 @@ namespace BlueWest.EfMethods
} }
foreach (var uProperty in getOneWithAttributesMembers) foreach (var uProperty in getOneMembers)
{ {
var entityDataModel = GetEntityData(uProperty, semanticModel); var entityDataModel = GetEntityData(uProperty, semanticModel);
var newUpdateModel = ExtractEfGetEntityWithModel(uProperty, semanticModel, entityDataModel); var newUpdateModel = ExtractEfGetEntityWithModel(uProperty, semanticModel, entityDataModel);
@ -303,13 +312,30 @@ namespace BlueWest.EfMethods
} }
foreach (var uProperty in getManyWithAttributesMembers) foreach (var uProperty in efGetManyMembers)
{ {
var entityDataModel = GetEntityData(uProperty, semanticModel); var entityDataModel = GetEntityData(uProperty, semanticModel);
var newUpdateModel = ExtractEfGetManyModel(uProperty, semanticModel, entityDataModel); var newUpdateModel = ExtractEfGetManyModel(uProperty, semanticModel, entityDataModel);
methodsModels.Add(newUpdateModel); methodsModels.Add(newUpdateModel);
} }
foreach (var uProperty in getListMembers)
{
var entityDataModel = GetEntityData(uProperty, semanticModel);
var newModel = ExtractEfGetListModel(uProperty, semanticModel, entityDataModel);
methodsModels.Add(newModel);
}
foreach (var uProperty in getAddToListMembers)
{
var entityDataModel = GetEntityData(uProperty, semanticModel);
var newModel = ExtractEfAddToListMethodsModel(uProperty, semanticModel, entityDataModel);
methodsModels.Add(newModel);
}
//SpinWait.SpinUntil(() => Debugger.IsAttached); //SpinWait.SpinUntil(() => Debugger.IsAttached);
@ -364,7 +390,7 @@ namespace BlueWest.EfMethods
GetEntityTypeSymbol(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel); GetEntityTypeSymbol(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel); var keyPropertyName = ExtractNameOfMemberName(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
var keyMemberType = FindFirstTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax); var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
//var secondTypeInfo = FindSecondTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax); //var secondTypeInfo = FindSecondTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
var keyMemberFullName = keyMemberType.Value.Type.ToDisplayString(); var keyMemberFullName = keyMemberType.Value.Type.ToDisplayString();
@ -453,7 +479,7 @@ namespace BlueWest.EfMethods
var efTypeofSymbols = GetEntityTypeSymbol(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel); var efTypeofSymbols = GetEntityTypeSymbol(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
var byParamPropertyName = ExtractNameOfMemberName(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel); var byParamPropertyName = ExtractNameOfMemberName(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
var keyMemberType = FindFirstTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax); var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
var byParamFullTypeName = keyMemberType.Value.Type.ToDisplayString(); var byParamFullTypeName = keyMemberType.Value.Type.ToDisplayString();
@ -483,6 +509,99 @@ namespace BlueWest.EfMethods
} }
private EfGetListModel ExtractEfGetListModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
{
var efTypeofSymbols = GetEntityTypeSymbol(uProperty, EfGetListAttributeSource.AttributeName, semanticModel);
var listPropertyName = ExtractNameOfMemberName(uProperty, EfGetListAttributeSource.AttributeName, semanticModel);
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfGetListAttributeSource.AttributeName, semanticModel, 1);;
var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
var keyFullTypeName = keyMemberType.Value.Type.ToDisplayString();
// Try grabbing string literal if there's no nameof in it
if (keyPropertyName == string.Empty)
{
listPropertyName = GetEntityStringLiteralSymbol(TypeSyntax, EfGetListAttributeSource.AttributeName, semanticModel)
.FirstOrDefault()?
.Token.ValueText ?? "Id";
}
string returnTypeIdentifierName = entityDataModel.EntityTypeIdentifierName;
string returnTypeFullName = entityDataModel.EntityTypeFullName;
// Grab return type from attribute argument
if (efTypeofSymbols.Length > 0)
{
returnTypeIdentifierName = efTypeofSymbols[0].Name;
returnTypeFullName = efTypeofSymbols[0].ToDisplayString();
}
return new EfGetListModel(entityDataModel, listPropertyName, keyPropertyName, keyFullTypeName, returnTypeIdentifierName, returnTypeFullName);
}
private EfAddToListModel ExtractEfAddToListMethodsModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
{
//SpinWait.SpinUntil(() => Debugger.IsAttached);
var efTypeofSymbols = GetEntityTypeSymbol(uProperty, EfAddToListAttributeSource.AttributeName, semanticModel);
var listPropertyName = ExtractNameOfMemberName(uProperty, EfAddToListAttributeSource.AttributeName, semanticModel);
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfAddToListAttributeSource.AttributeName, semanticModel, 1);;
var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
var keyFullTypeName = keyMemberType.Value.Type.ToDisplayString();
var listEntityTypeInfo = (FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax, 2).Value.Type as INamedTypeSymbol).TypeArguments.FirstOrDefault();
var listEntityIdentifierName = listEntityTypeInfo.Name;
var listEntityFullTypeName = listEntityTypeInfo.ToDisplayString();
// Try grabbing string literal if there's no nameof in it
if (keyPropertyName == string.Empty)
{
listPropertyName = GetEntityStringLiteralSymbol(TypeSyntax, EfAddToListAttributeSource.AttributeName, semanticModel)
.FirstOrDefault()?
.Token.ValueText ?? "Id";
}
string returnTypeIdentifierName = entityDataModel.EntityTypeIdentifierName;
string returnTypeFullName = entityDataModel.EntityTypeFullName;
var createTypeIdentifierName =listEntityIdentifierName;
var createTypeFullName = listEntityFullTypeName;
// Grab create type from attribute argument
if (efTypeofSymbols.Length > 0)
{
createTypeIdentifierName = efTypeofSymbols[0].Name;
createTypeFullName = efTypeofSymbols[0].ToDisplayString();
}
// Grab return type from attribute argument
if (efTypeofSymbols.Length > 1)
{
returnTypeIdentifierName = efTypeofSymbols[1].Name;
returnTypeFullName = efTypeofSymbols[1].ToDisplayString();
}
return new EfAddToListModel(
entityDataModel,
listPropertyName,
listEntityIdentifierName,
listEntityFullTypeName,
keyPropertyName,
keyFullTypeName,
createTypeIdentifierName,
createTypeFullName,
returnTypeIdentifierName,
returnTypeFullName);
}
private static ITypeSymbol GetEntityTypeData(MemberDeclarationSyntax memberDeclarationSyntax, SemanticModel? semanticModel = null) private static ITypeSymbol GetEntityTypeData(MemberDeclarationSyntax memberDeclarationSyntax, SemanticModel? semanticModel = null)
{ {
var member = (memberDeclarationSyntax as PropertyDeclarationSyntax).Type; var member = (memberDeclarationSyntax as PropertyDeclarationSyntax).Type;

View File

@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using BlueWest.EfMethods.EfMethods.AttributeSources;
using BlueWest.EfMethods.Extensions; using BlueWest.EfMethods.Extensions;
using BlueWest.EfMethods.Sources; using BlueWest.EfMethods.Sources;
using BlueWest.Sources;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
@ -35,7 +37,11 @@ namespace BlueWest.EfMethods
.AddSource(ref context, EfUpdateMethodsAttributeSource.Generate(options)) .AddSource(ref context, EfUpdateMethodsAttributeSource.Generate(options))
.AddSource(ref context, EfGetOneByAttributeSource.Generate(options)) .AddSource(ref context, EfGetOneByAttributeSource.Generate(options))
.AddSource(ref context, EfGetOneAttributeSource.Generate(options)) .AddSource(ref context, EfGetOneAttributeSource.Generate(options))
.AddSource(ref context, EfGetManyAttributeSource.Generate(options)); .AddSource(ref context, EfGetManyAttributeSource.Generate(options))
.AddSource(ref context, EfGetListAttributeSource.Generate(options))
.AddSource(ref context, EfAddToListAttributeSource.Generate(options));
if (context.SyntaxReceiver is EfMethodsSyntaxReceiver receiver && receiver.CandidateTypes.Any()) if (context.SyntaxReceiver is EfMethodsSyntaxReceiver receiver && receiver.CandidateTypes.Any())
@ -50,15 +56,29 @@ namespace BlueWest.EfMethods
} }
} }
private static EfTemplates GetAvailableTemplates(GeneratorExecutionContext context)
{
string addSourceTemplate = GetCsxMethodTemplate(context, "AddToTemplate");
string updateSourceTemplate = GetCsxMethodTemplate(context, "UpdateTemplate");
string getOneByTemplate = GetCsxMethodTemplate(context, "GetOneByTemplate");
string getOneTemplate = GetCsxMethodTemplate(context, "GetOneTemplate");
string getManyWithTemplate = GetCsxMethodTemplate(context, "GetManyTemplate");
string getListTemplate = GetCsxMethodTemplate(context, "GetListTemplate");
string addToListTemplate = GetCsxMethodTemplate(context, "AddToListTemplate");
return new EfTemplates(
addSourceTemplate,
updateSourceTemplate,
getOneByTemplate,
getOneTemplate,
getManyWithTemplate,
getListTemplate,
addToListTemplate);
}
private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable<TypeDeclarationSyntax> candidateMembers, SourceGenerationOptions options) private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable<TypeDeclarationSyntax> candidateMembers, SourceGenerationOptions options)
{ {
string addSourceTemplate = GetCsxMethodTemplate(context, "AddToEntityTemplate"); var templates = GetAvailableTemplates(context);
string updateSourceTemplate = GetCsxMethodTemplate(context, "UpdateEntityTemplate");
string getOneByTemplate = GetCsxMethodTemplate(context, "GetOneByTemplate");
string getOneWithByTemplate = GetCsxMethodTemplate(context, "GetOneTemplate");
string getManyWithTemplate = GetCsxMethodTemplate(context, "GetManyTemplate");
foreach (var candidateMember in candidateMembers) foreach (var candidateMember in candidateMembers)
{ {
@ -76,11 +96,7 @@ namespace BlueWest.EfMethods
{ {
ClassDeclarationSyntax => EfMethodsSource.Generate( ClassDeclarationSyntax => EfMethodsSource.Generate(
mappingContext.Model, mappingContext.Model,
addSourceTemplate, templates),
updateSourceTemplate,
getOneByTemplate,
getOneWithByTemplate,
getManyWithTemplate),
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };

View File

@ -11,19 +11,10 @@ namespace BlueWest.EfMethods.Sources
{ {
internal static class EfMethodsSource internal static class EfMethodsSource
{ {
internal static SourceCode Generate(EfMethodsModel model, internal static SourceCode Generate(EfMethodsModel model, EfTemplates templates)
string addSourceTemplate,
string updateSourceTemplate,
string getOneBySourceTemplate,
string getOneWithSourceTemplate,
string getManyWithSourceTemplate
)
{ {
using var builder = new SourceBuilder(); using var builder = new SourceBuilder();
var contextFullName = model.ContextFullType;
builder builder
.WriteLine(GeneratedFilesHeader) .WriteLine(GeneratedFilesHeader)
.WriteUsings(model.Usings) .WriteUsings(model.Usings)
@ -31,7 +22,6 @@ namespace BlueWest.EfMethods.Sources
.WriteLine("using System.Linq;") .WriteLine("using System.Linq;")
.WriteLine("using System.Linq.Expressions;") .WriteLine("using System.Linq.Expressions;")
.WriteLine("using System.Threading.Tasks;") .WriteLine("using System.Threading.Tasks;")
.WriteLine() .WriteLine()
// Namespace declaration // Namespace declaration
.WriteLine($"namespace {model.Namespace}") .WriteLine($"namespace {model.Namespace}")
@ -41,44 +31,51 @@ namespace BlueWest.EfMethods.Sources
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteLine(); .WriteLine();
foreach (var methodModel in model.MethodsModels.OrderBy(x => x.PropertyName)) foreach (var methodModel in model.MethodsModels.OrderBy(x => x.PropertyName))
{ {
switch (methodModel) switch (methodModel)
{ {
case EfAddMethodsModel modl: case EfAddMethodsModel currentModel:
builder builder
.EfAddAddEntityMethod(model, modl, addSourceTemplate) .EfAddAddMethod(model, currentModel, templates.AddTemplate)
.WriteLine(); .WriteLine();
break; break;
case EfUpdateMethodsModel modl: case EfUpdateMethodsModel currentModel:
builder builder
.EfAddUpdateEntityMethod(model, modl, updateSourceTemplate) .EfAddUpdateMethod(model, currentModel, templates.UpdateTemplate)
.WriteLine(); .WriteLine();
break; break;
case EfGetOneByModel modl: case EfGetOneByModel currentModel:
builder builder
.EfAddGetOneEntityByMethod(model, modl, getOneBySourceTemplate) .EfAddGetOneEntityByMethod(model, currentModel, templates.GetOneByTemplate)
.WriteLine(); .WriteLine();
break;
case EfGetManyModel modl:
builder
.EfAddGetManyWithMethod(model, modl, getManyWithSourceTemplate)
.WriteLine();
break;
case EfGetOneWithModel modl:
builder
.EfAddGetOneEntityWithMethod(model, modl, getOneWithSourceTemplate)
.WriteLine();
break; break;
case EfGetManyModel currentModel:
builder
.EfAddGetManyMethod(model, currentModel, templates.GetManyTemplate)
.WriteLine();
break;
case EfGetOneWithModel currentModel:
builder
.EfAddGetOneMethod(model, currentModel, templates.GetOneTemplate)
.WriteLine();
break;
case EfGetListModel currentModel:
builder
.EfAddGetListMethod(model, currentModel, templates.GetListTemplate)
.WriteLine();
break;
case EfAddToListModel currentModel:
builder
.EfAddAddToListMethod(model, currentModel, templates.AddToListTemplate)
.WriteLine();
break;
} }
} }
builder builder
@ -105,9 +102,5 @@ namespace BlueWest.EfMethods.Sources
return builder; return builder;
} }
} }
} }

View File

@ -1,13 +1,12 @@
using BlueWest.EfMethods.Extensions; using BlueWest.EfMethods.Extensions;
using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using BlueWest.EfMethods.Sources;
namespace BlueWest.EfMethods.Sources namespace BlueWest.EfMethods
{ {
internal static class EfAddEntityTemplateSource internal static class EfAddEntityTemplateSource
{ {
internal static SourceBuilder EfAddAddEntityMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfAddMethodsModel model, string addSourceTemplate) internal static SourceBuilder EfAddAddMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfAddMethodsModel model, string addSourceTemplate)
{ {
var returnTypeFullName = model.ReturnTypeFullName; var returnTypeFullName = model.ReturnTypeFullName;
var createTypeFullName = model.CreateTypeFullName; var createTypeFullName = model.CreateTypeFullName;

View File

@ -0,0 +1,78 @@
using System.Text;
using BlueWest.EfMethods.Extensions;
using BlueWest.EfMethods.Sources;
namespace BlueWest.EfMethods
{
internal static class EfAddToListTemplateSource
{
internal static SourceBuilder EfAddAddToListMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfAddToListModel model, string template)
{
var returnTypeFullName = model.ReturnTypeFullName;
var entityTypeName = model.EntityTypeIdentifierName;
var listPropertyName = model.ListPropertyName;
var listEntityCreateFullName = model.CreateTypeFullName;
var listItemCreateVarName = model.ListEntityIdentifierName.ToCamelCase() + "toCreate";
var listEntityTypeName = model.ListEntityIdentifierName;
var listEntityFullName = model.ListEntityFullTypeName;
var contextFullName = methodsModel.ContextFullType;
var propertyName = model.PropertyName;
var primaryKeyFullName = model.KeyFullTypeName;
var primaryKeyPropertyName = model.KeyPropertyName;
var primaryKeyVarName = model.KeyPropertyName.ToCamelCase();
var entityObjectVarName = model.EntityTypeIdentifierName.ToCamelCase();
if (!template.IsEmpty())
{
var templateToSourceBuilder = new StringBuilder(template);
templateToSourceBuilder
.Replace("{returnTypeFullName}", returnTypeFullName)
.Replace("{entityTypeName}", entityTypeName)
.Replace("{contextFullName}", contextFullName)
.Replace("{listPropertyName}", listPropertyName)
.Replace("{primaryKeyPropertyName}", primaryKeyPropertyName)
.Replace("{primaryKeyFullName}", primaryKeyFullName)
.Replace("{primaryKeyVarName}", primaryKeyVarName)
.Replace("{entityObjectVarName}", entityObjectVarName)
.Replace("{propertyName}", propertyName)
.Replace("{listEntityCreateFullName}", listEntityCreateFullName)
.Replace("{listEntityTypeName}", listEntityTypeName)
.Replace("{listEntityFullName}", listEntityFullName)
.Replace("{listItemCreateVarName}", listItemCreateVarName)
.Replace("{primaryKeyPropertyName}", primaryKeyPropertyName);
builder
.ParseTemplate(templateToSourceBuilder.ToString());
}
if (template.IsEmpty())
{
builder
.WriteComment("Generated body")
//.WriteLine(GeneratedFilesHeader)
.WriteLine($"public static (bool, string, {returnTypeFullName}) Add{listEntityTypeName}To{entityTypeName}( this {contextFullName} dbContext, {primaryKeyFullName} {primaryKeyVarName}, {listEntityCreateFullName} {listItemCreateVarName})")
.WriteOpeningBracket()
.WriteLine($"var entityQuery = from aEntity in dbContext.{propertyName}")
.WriteLine($"where aEntity.{primaryKeyVarName} == {primaryKeyVarName}")
.WriteLine($"let itemsInList = aEntity.{listPropertyName}")
.WriteLine($"select aEntity;")
.WriteLine()
.WriteLine($"var entity = entityQuery.FirstOrDefault();")
.WriteLine($"if (entity == null) return (false, $\"{entityTypeName} not found.\", null);")
.WriteLine($"var newListItem = new {listEntityFullName}({listItemCreateVarName});")
.WriteLine($"entity.{listPropertyName}.Add({listItemCreateVarName});")
.WriteLine($"var success = dbContext.SaveChanges() >= 0;")
.WriteLine($"return !success ? (false, \"Error saving changes in the Database. Action: Create {listEntityTypeName} in {entityTypeName}.\", null) : (true, string.Empty, new {returnTypeFullName}(newListItem));")
.WriteClosingBracket();
builder
.WriteLine();
}
return builder;
}
}
}

View File

@ -0,0 +1,68 @@
using System.Text;
using BlueWest.EfMethods.Extensions;
using BlueWest.EfMethods.Sources;
namespace BlueWest.EfMethods
{
public static class EfGetListTemplateSource
{
internal static SourceBuilder EfAddGetListMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfGetListModel model, string addSourceTemplate)
{
var returnTypeFullName = model.ReturnTypeFullName;
var entityTypeName = model.EntityTypeIdentifierName;
var listPropertyName = model.ListPropertyName;
var contextFullName = methodsModel.ContextFullType;
var propertyName = model.PropertyName;
var primaryKeyFullName = model.KeyFullTypeName;
var primaryKeyPropertyName = model.KeyPropertyName;
var primaryKeyVarName = model.KeyPropertyName.ToCamelCase();
var entityObjectVarName = model.EntityTypeIdentifierName.ToCamelCase();
if (!addSourceTemplate.IsEmpty())
{
var templateToSourceBuilder = new StringBuilder(addSourceTemplate);
templateToSourceBuilder
.Replace("{returnTypeFullName}", returnTypeFullName)
.Replace("{entityTypeName}", entityTypeName)
.Replace("{contextFullName}", contextFullName)
.Replace("{listPropertyName}", listPropertyName)
.Replace("{primaryKeyPropertyName}", primaryKeyPropertyName)
.Replace("{primaryKeyFullName}", primaryKeyFullName)
.Replace("{primaryKeyVarName}", primaryKeyVarName)
.Replace("{entityObjectVarName}", entityObjectVarName)
.Replace("{propertyName}", propertyName);
builder
.ParseTemplate(templateToSourceBuilder.ToString());
}
if (addSourceTemplate.IsEmpty())
{
builder
.WriteComment("Generated body")
//.WriteLine(GeneratedFilesHeader)
.WriteLine($"public static (bool, {returnTypeFullName}[]) Get{entityTypeName}{listPropertyName}(this {contextFullName} dbContext, {primaryKeyFullName} {primaryKeyVarName},")
.WriteLine($"int skip = 0, int take = 50, int orderDir = 1, Expression<Func<{returnTypeFullName}, bool>> orderBy = null)")
.WriteOpeningBracket()
.WriteLine($"var {entityObjectVarName} = dbContext.{propertyName}.FirstOrDefault(d => d.{primaryKeyPropertyName} == {primaryKeyVarName});")
.WriteLine($"if ({entityObjectVarName} == null) return (false, null);")
.WriteLine($"var currentTake = take;")
.WriteLine($"if (take > 200) currentTake = 200;")
.WriteLine($"var query = dbContext")
.WriteLine($".{propertyName}")
.WriteLine($".Where(data => data.{primaryKeyPropertyName} == {primaryKeyVarName})")
.WriteLine($".SelectMany(o => o.{listPropertyName})")
.WriteLine($".Select(x => new {returnTypeFullName}(x))")
.WriteLine($".Skip(skip)")
.WriteLine($"if(orderBy != null) query = orderDir == 1 ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);")
.WriteLine($"return (query.Any(), query.ToArray());")
.WriteClosingBracket();
builder
.WriteLine();
}
return builder;
}
}
}

View File

@ -28,7 +28,6 @@ namespace BlueWest.EfMethods
.Replace("{entityTypeName}", entityTypeName) .Replace("{entityTypeName}", entityTypeName)
.Replace("{byParamPropertyName}", byParamPropertyName) .Replace("{byParamPropertyName}", byParamPropertyName)
.Replace("{contextFullName}", contextFullName) .Replace("{contextFullName}", contextFullName)
.Replace("{contextFullName}", contextFullName)
.Replace("{byParamFullType}", byParamFullType) .Replace("{byParamFullType}", byParamFullType)
.Replace("{byParamVarName}", byParamVarName) .Replace("{byParamVarName}", byParamVarName)

View File

@ -8,7 +8,7 @@ namespace BlueWest.EfMethods
{ {
internal static class EfGetOneWithTemplateSource internal static class EfGetOneWithTemplateSource
{ {
internal static SourceBuilder EfAddGetOneEntityWithMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfGetOneWithModel model, string addSourceTemplate) internal static SourceBuilder EfAddGetOneMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfGetOneWithModel model, string addSourceTemplate)
{ {
var returnTypeFullName = model.ReturnTypeFullName; var returnTypeFullName = model.ReturnTypeFullName;
var entityTypeName = model.EntityTypeIdentifierName; var entityTypeName = model.EntityTypeIdentifierName;
@ -53,7 +53,7 @@ namespace BlueWest.EfMethods
return builder; return builder;
} }
internal static SourceBuilder EfAddGetManyWithMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfGetManyModel model, string addSourceTemplate) internal static SourceBuilder EfAddGetManyMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfGetManyModel model, string addSourceTemplate)
{ {
var returnTypeFullName = model.ReturnTypeFullName; var returnTypeFullName = model.ReturnTypeFullName;
var entityTypeName = model.EntityTypeIdentifierName; var entityTypeName = model.EntityTypeIdentifierName;

View File

@ -7,7 +7,7 @@ namespace BlueWest.EfMethods.Sources
{ {
internal static class EfUpdateEntityTemplateSource internal static class EfUpdateEntityTemplateSource
{ {
internal static SourceBuilder EfAddUpdateEntityMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfUpdateMethodsModel model, string updateSourceTemplate) internal static SourceBuilder EfAddUpdateMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfUpdateMethodsModel model, string updateSourceTemplate)
{ {
var entityTypeName = model.EntityTypeIdentifierName; var entityTypeName = model.EntityTypeIdentifierName;
var contextFullName = methodsModel.ContextFullType; var contextFullName = methodsModel.ContextFullType;

View File

@ -32,6 +32,17 @@ namespace BlueWest.EfMethods
ImmutableArray<string> Usings ImmutableArray<string> Usings
); );
record EfTemplates(
string AddTemplate,
string UpdateTemplate,
string GetOneByTemplate,
string GetOneTemplate,
string GetManyTemplate,
string GetListTemplate,
string AddToListTemplate
);
internal class EfEntityDataModel internal class EfEntityDataModel
{ {
public string PropertyName { get; set; } public string PropertyName { get; set; }
@ -90,8 +101,8 @@ namespace BlueWest.EfMethods
internal class EfGetOneWithModel : EfEntityDataModel internal class EfGetOneWithModel : EfEntityDataModel
{ {
public string ReturnTypeIdentifierName { get; set; } public string ReturnTypeIdentifierName { get; }
public string ReturnTypeFullName { get; set; } public string ReturnTypeFullName { get; }
public EfGetOneWithModel(EfEntityDataModel entity, string returnTypeFullName, public EfGetOneWithModel(EfEntityDataModel entity, string returnTypeFullName,
string returnTypeIdentifierName) : base(entity.PropertyName, entity.EntityTypeFullName, entity.EntityTypeIdentifierName) string returnTypeIdentifierName) : base(entity.PropertyName, entity.EntityTypeFullName, entity.EntityTypeIdentifierName)
@ -119,10 +130,10 @@ namespace BlueWest.EfMethods
{ {
public string UpdateTypeFullName; public string UpdateTypeFullName;
public string UpdateTypeIdentifierName; public string UpdateTypeIdentifierName;
public string ReturnTypeFullName; public readonly string ReturnTypeFullName;
public string ReturnTypeIdentifierName; public string ReturnTypeIdentifierName;
public string KeyPropertyName; public readonly string KeyPropertyName;
public string KeyFullTypeName; public readonly string KeyFullTypeName;
public EfUpdateMethodsModel(EfEntityDataModel entity, public EfUpdateMethodsModel(EfEntityDataModel entity,
string updateTypeFullName, string updateTypeFullName,
string updateTypeIdentifierName, string updateTypeIdentifierName,
@ -140,6 +151,80 @@ namespace BlueWest.EfMethods
} }
} }
internal class EfGetListModel : EfEntityDataModel
{
public string ListPropertyName { get; set; }
public string KeyPropertyName { get; set; }
public string KeyFullTypeName { get; set; }
public string ReturnTypeIdentifierName { get; set; }
public string ReturnTypeFullName { get; set; }
public EfGetListModel(
EfEntityDataModel entity,
string listPropertyName,
string keyPropertyName,
string keyFullTypeName,
string returnTypeIdentifierName,
string returnTypeFullName)
: base(entity.PropertyName, entity.EntityTypeFullName, entity.EntityTypeIdentifierName)
{
ListPropertyName = listPropertyName;
KeyPropertyName = keyPropertyName;
KeyFullTypeName = keyFullTypeName;
ReturnTypeIdentifierName = returnTypeIdentifierName;
ReturnTypeFullName = returnTypeFullName;
}
}
internal class EfAddToListModel : EfEntityDataModel
{
public string ListPropertyName { get; set; }
public string ListEntityIdentifierName { get; set; }
public string ListEntityFullTypeName { get; set; }
public string KeyPropertyName { get; set; }
public string KeyFullTypeName { get; set; }
public string CreateTypeIdentifierName { get; set; }
public string CreateTypeFullName { get; set; }
public string ReturnTypeIdentifierName { get; set; }
public string ReturnTypeFullName { get; set; }
public EfAddToListModel(
EfEntityDataModel entity,
string listPropertyName,
string listEntityIdentifierName,
string listEntityFullTypeName,
string keyPropertyName,
string keyFullTypeName,
string createTypeIdentifierName,
string createTypeFullName,
string returnTypeIdentifierName,
string returnTypeFullName)
: base(entity.PropertyName, entity.EntityTypeFullName, entity.EntityTypeIdentifierName)
{
ListPropertyName = listPropertyName;
ListEntityIdentifierName = listEntityIdentifierName;
ListEntityFullTypeName = listEntityFullTypeName;
KeyPropertyName = keyPropertyName;
KeyFullTypeName = keyFullTypeName;
CreateTypeIdentifierName = createTypeIdentifierName;
CreateTypeFullName = createTypeFullName;
ReturnTypeIdentifierName = returnTypeIdentifierName;
ReturnTypeFullName = returnTypeFullName;
}
}
internal record SourceGenerationOptions( internal record SourceGenerationOptions(
AccessModifier ConstructorAccessModifier, AccessModifier ConstructorAccessModifier,
AccessModifier GeneratedMethodsAccessModifier, AccessModifier GeneratedMethodsAccessModifier,