private static void GenerateModels(ModelOptions opt) { using var dynamicContext = new AssemblyResolver(Path.GetFullPath(opt.Assembly)); var assembly = dynamicContext.Assembly; var codeGenConfig = new CodeGenerationConfig(); codeGenConfig.Scan(assembly); var types = assembly.GetTypes().ToHashSet(); foreach (var builder in codeGenConfig.AdaptAttributeBuilders) { foreach (var setting in builder.TypeSettings) { types.Add(setting.Key); } } foreach (var type in types) { var builders = type.GetAdaptAttributeBuilders(codeGenConfig) .Where(it => !string.IsNullOrEmpty(it.Attribute.Name) && it.Attribute.Name != "[name]") .ToList(); if (builders.Count == 0) { continue; } Console.WriteLine($"Processing: {type.FullName}"); foreach (var builder in builders) { CreateModel(opt, type, builder); } } }
private static void CreateModel(ModelOptions opt, Type type, BaseAdaptAttribute attr) { var definitions = new TypeDefinitions { Namespace = opt.Namespace ?? type.Namespace, TypeName = attr.Name !.Replace("[name]", type.Name), PrintFullTypeName = opt.PrintFullTypeName, }; var translator = new ExpressionTranslator(definitions); var isAdaptTo = attr is AdaptToAttribute; var isTwoWays = attr is AdaptTwoWaysAttribute; var side = isAdaptTo ? MemberSide.Source : MemberSide.Destination; var properties = type.GetFieldsAndProperties().Where(it => !it.SafeGetCustomAttributes().OfType <AdaptIgnoreAttribute>() .Any(it2 => isTwoWays || it2.Side == null || it2.Side == side)); if (attr.IgnoreAttributes != null) { properties = properties.Where(it => !it.SafeGetCustomAttributes() .Select(it2 => it2.GetType()) .Intersect(attr.IgnoreAttributes) .Any()); } if (attr.IgnoreNoAttributes != null) { properties = properties.Where(it => it.SafeGetCustomAttributes() .Select(it2 => it2.GetType()) .Intersect(attr.IgnoreNoAttributes) .Any()); } if (attr.IgnoreNamespaces != null) { foreach (var ns in attr.IgnoreNamespaces) { properties = properties.Where(it => getPropType(it).Namespace?.StartsWith(ns) != true); } } var isReadOnly = isAdaptTo && attr.MapToConstructor; var isNullable = !isAdaptTo && attr.IgnoreNullValues; foreach (var member in properties) { var adaptMember = member.GetCustomAttribute <AdaptMemberAttribute>(); var propType = GetPropertyType(member, getPropType(member), attr.GetType(), opt.Namespace); translator.Properties.Add(new PropertyDefinitions { Name = adaptMember?.Name ?? member.Name, Type = isNullable ? propType.MakeNullable() : propType, IsReadOnly = isReadOnly }); } var code = translator.ToString(); var path = Path.Combine(Path.GetFullPath(opt.Output), definitions.TypeName + ".g.cs"); WriteFile(code, path);
private static void GenerateModels(ModelOptions opt) { using var dynamicContext = new AssemblyResolver(Path.GetFullPath(opt.Assembly)); var assembly = dynamicContext.Assembly; foreach (var type in assembly.GetTypes()) { var attrs = type.SafeGetCustomAttributes() .OfType <BaseAdaptAttribute>() .Where(it => !string.IsNullOrEmpty(it.Name) && it.Name != "[name]") .ToList(); if (attrs.Count == 0) { continue; } Console.WriteLine($"Processing: {type.FullName}"); foreach (var attr in attrs) { CreateModel(opt, type, attr); } } }
private static void CreateModel(ModelOptions opt, Type type, AdaptAttributeBuilder builder) { var segments = GetSegments(type.Namespace, opt.BaseNamespace); var attr = builder.Attribute; var definitions = new TypeDefinitions { Namespace = CreateNamespace(opt.Namespace, segments, type.Namespace), TypeName = attr.Name !.Replace("[name]", type.Name), PrintFullTypeName = opt.PrintFullTypeName, IsRecordType = opt.IsRecordType, NullableContext = GetTypeNullableContext(type), }; var translator = new ExpressionTranslator(definitions); var isAdaptTo = attr is AdaptToAttribute; var isTwoWays = attr is AdaptTwoWaysAttribute; var side = isAdaptTo ? MemberSide.Source : MemberSide.Destination; var properties = type.GetFieldsAndProperties().Where(it => !it.SafeGetCustomAttributes().OfType <AdaptIgnoreAttribute>() .Any(it2 => isTwoWays || it2.Side == null || it2.Side == side)); if (attr.IgnoreAttributes != null) { properties = properties.Where(it => !it.SafeGetCustomAttributes() .Select(it2 => it2.GetType()) .Intersect(attr.IgnoreAttributes) .Any()); } if (attr.IgnoreNoAttributes != null) { properties = properties.Where(it => it.SafeGetCustomAttributes() .Select(it2 => it2.GetType()) .Intersect(attr.IgnoreNoAttributes) .Any()); } if (attr.IgnoreNamespaces != null) { foreach (var ns in attr.IgnoreNamespaces) { properties = properties.Where(it => getPropType(it).Namespace?.StartsWith(ns) != true); } } var propSettings = builder.TypeSettings.GetValueOrDefault(type); var isReadOnly = isAdaptTo && attr.MapToConstructor; var isNullable = !isAdaptTo && attr.IgnoreNullValues; foreach (var member in properties) { var setting = propSettings?.GetValueOrDefault(member.Name); if (setting?.Ignore == true) { continue; } var adaptMember = member.GetCustomAttribute <AdaptMemberAttribute>(); if (!isTwoWays && adaptMember?.Side != null && adaptMember.Side != side) { adaptMember = null; } var propType = setting?.MapFunc?.ReturnType ?? setting?.TargetPropertyType ?? GetPropertyType(member, getPropType(member), attr.GetType(), opt.Namespace, builder); var nilAttr = member.GetCustomAttributesData() .FirstOrDefault(it => it.AttributeType.Name == "NullableAttribute"); var nilAttrArg = nilAttr?.ConstructorArguments.Count == 1 ? nilAttr.ConstructorArguments[0].Value : null; translator.Properties.Add(new PropertyDefinitions { Name = setting?.TargetPropertyName ?? adaptMember?.Name ?? member.Name, Type = isNullable ? propType.MakeNullable() : propType, IsReadOnly = isReadOnly, NullableContext = nilAttrArg is byte b ? (byte?)b : null, Nullable = nilAttrArg is byte[] bytes ? bytes : null, });