public void TestExtensionMethod() { var p1 = Expression.Parameter(typeof(int)); var p2 = Expression.Parameter(typeof(int)); var lambda = Expression.Lambda <Func <int, int, int> >( Expression.Add(p1, p2), p1, p2); var translator = new ExpressionTranslator(new TypeDefinitions { IsStatic = true, Namespace = "ExpressionDebugger.Tests", TypeName = "MockClass" }); translator.VisitLambda(lambda, ExpressionTranslator.LambdaType.ExtensionMethod, "Add"); var str = translator.ToString(); Assert.AreEqual(@" namespace ExpressionDebugger.Tests { public static partial class MockClass { public static int Add(this int p1, int p2) { return p1 + p2; } } }".Trim(), str); }
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);
public void TestProperties() { var translator = new ExpressionTranslator(new TypeDefinitions { IsStatic = false, Namespace = "ExpressionDebugger.Tests", TypeName = "MockClass" }); translator.Properties.Add(new PropertyDefinitions { Name = "Prop1", Type = typeof(string) }); translator.Properties.Add(new PropertyDefinitions { Name = "Prop2", Type = typeof(string), IsReadOnly = true }); var str = translator.ToString(); Assert.AreEqual(@" namespace ExpressionDebugger.Tests { public partial class MockClass { public string Prop1 { get; set; } public string Prop2 { get; } public MockClass(string prop2) { this.Prop2 = prop2; } } }".Trim(), str); }
private static void GenerateMappers(MapperOptions opt) { using var dynamicContext = new AssemblyResolver(Path.GetFullPath(opt.Assembly)); var assembly = dynamicContext.Assembly; var config = TypeAdapterConfig.GlobalSettings; config.SelfContainedCodeGeneration = true; config.Scan(assembly); foreach (var type in assembly.GetTypes()) { if (!type.IsInterface) { continue; } var attr = type.GetCustomAttribute <MapperAttribute>(); if (attr == null) { continue; } Console.WriteLine($"Processing: {type.FullName}"); var definitions = new TypeDefinitions { Implements = new[] { type }, Namespace = opt.Namespace ?? type.Namespace, TypeName = attr.Name ?? GetImplName(type.Name), IsInternal = attr.IsInternal, PrintFullTypeName = opt.PrintFullTypeName, }; var translator = new ExpressionTranslator(definitions); var interfaces = type.GetAllInterfaces(); foreach (var @interface in interfaces) { foreach (var prop in @interface.GetProperties()) { if (!prop.PropertyType.IsGenericType) { continue; } if (prop.PropertyType.GetGenericTypeDefinition() != typeof(Expression <>)) { continue; } var propArgs = prop.PropertyType.GetGenericArguments()[0]; if (!propArgs.IsGenericType) { continue; } if (propArgs.GetGenericTypeDefinition() != typeof(Func <,>)) { continue; } var funcArgs = propArgs.GetGenericArguments(); var tuple = new TypeTuple(funcArgs[0], funcArgs[1]); var expr = config.CreateMapExpression(tuple, MapType.Projection); translator.VisitLambda(expr, ExpressionTranslator.LambdaType.PublicLambda, prop.Name); } } foreach (var @interface in interfaces) { foreach (var method in @interface.GetMethods()) { if (method.IsGenericMethod) { continue; } if (method.ReturnType == typeof(void)) { continue; } var methodArgs = method.GetParameters(); if (methodArgs.Length < 1 || methodArgs.Length > 2) { continue; } var tuple = new TypeTuple(methodArgs[0].ParameterType, method.ReturnType); var expr = config.CreateMapExpression(tuple, methodArgs.Length == 1 ? MapType.Map : MapType.MapToTarget); translator.VisitLambda(expr, ExpressionTranslator.LambdaType.PublicMethod, method.Name); } } var code = translator.ToString(); var path = Path.Combine(Path.GetFullPath(opt.Output), definitions.TypeName + ".g.cs"); WriteFile(code, path); } }