private AggregateFunctionContext CreateMemberContext(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, FunctionMap functionMap) { Type implementationType = functionMap.GetTypeForFunction(member.AggregateMappingDescription.FunctionName); string functionObjectName = string.Format("_{0}_to_{1}_Fn_", member.AggregateMappingDescription.FunctionObject, member.Member); if (implementationType.IsGenericType) { if (member.IsArray || member.IsList) { Type instanceType = member.IsArray ? member.AggregateMappingDescription.TargetType.GetElementType() : member.AggregateMappingDescription.TargetType.GetGenericArguments()[0]; implementationType = implementationType.MakeGenericType(instanceType); } else { implementationType = implementationType.MakeGenericType(member.AggregateMappingDescription.TargetType); } } IAggregateFunctionCodeGenerator generator = GetGeneratorImpl(implementationType, member); return new AggregateFunctionContext(member, descriptor, implementationType, functionObjectName, generator); }
public void AddMapping(ClassMappingDescriptor descriptor, CodeGeneratorContext context) { CodeMemberMethod methodAssembleFrom = m_generator.CreateTypeTransformationMethod(descriptor); m_assemblerClass.Members.Add(methodAssembleFrom); CodeMemberMethod methodAssemble = m_generator.CreateInPlaceTransformationMethod(descriptor); m_assemblerClass.Members.Add(methodAssemble); CodeMemberMethod methodAssembleValueType = m_generator.CreateInPlaceTransformationMethodForValueTypes(descriptor); m_assemblerClass.Members.Add(methodAssembleValueType); CodeMemberMethod methodToList = m_generator.CreateToListMethod(descriptor); m_assemblerClass.Members.Add(methodToList); CodeMemberMethod methodToArray = m_generator.CreateToArrayMethod(descriptor); m_assemblerClass.Members.Add(methodToArray); string interfaceType = string.Format("IAssembler<{0}, {1}>", TypeHelper.GetTypeDefinition(descriptor.TargetType), TypeHelper.GetTypeDefinition(descriptor.SourceType)); m_assemblerClass.BaseTypes.Add(interfaceType); AddReferencedAssemblies(descriptor); }
private static void CopyMemberDescriptors(ClassMappingDescriptor from, ClassMappingDescriptor to) { foreach (MemberMappingDescriptor fromMember in from.MemberDescriptors) { // check if the member mapping is overriden in the derived class - do // not copy in that case bool overriden = false; foreach (MemberMappingDescriptor derivedMember in to.MemberDescriptors) { if (!fromMember.Member.Equals(derivedMember.Member)) { continue; } overriden = true; break; } if (overriden) { continue; } MemberMappingDescriptor toMember = new MemberMappingDescriptor(fromMember); toMember.OwnerType = to.TargetType; // check if the member is visible in the derived type MemberInfo member = FindMember(to.TargetType, toMember.Member); if (member != null) { to.MemberDescriptors.Add(toMember); } } }
private static ClassMappingDescriptor CreateMapping(Type type) { ClassMappingDescriptor desc = new ClassMappingDescriptor(); desc.TargetType = type; object[] attrs = type.GetCustomAttributes(typeof(MapClassAttribute), false); MapClassAttribute attr = (MapClassAttribute)attrs[0]; // todo: assert (should be exactly 1) desc.SourceType = attr.SourceType; desc.MappingHelper = attr.Helper; if (desc.HasHelper) { desc.IsHelperStatic = desc.MappingHelper.Contains("."); // todo: smarter assumption } desc.MappingPreparer = attr.Preparer; if (desc.HasPreparer) { desc.IsPreparerStatic = desc.MappingPreparer.Contains("."); // todo: smarter assumption } AddMemberDescriptors(desc); AddPreparerMethod(desc); AddHelperMethod(desc); return(desc); }
private AggregateFunctionContext CreateMemberContext(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, FunctionMap functionMap) { Type implementationType = functionMap.GetTypeForFunction(member.AggregateMappingDescription.FunctionName); string functionObjectName = string.Format("_{0}_to_{1}_Fn_", member.AggregateMappingDescription.FunctionObject, member.Member); if (implementationType.IsGenericType) { if (member.IsArray || member.IsList) { Type instanceType = member.IsArray ? member.AggregateMappingDescription.TargetType.GetElementType() : member.AggregateMappingDescription.TargetType.GetGenericArguments()[0]; implementationType = implementationType.MakeGenericType(instanceType); } else { implementationType = implementationType.MakeGenericType(member.AggregateMappingDescription.TargetType); } } IAggregateFunctionCodeGenerator generator = GetGeneratorImpl(implementationType, member); return(new AggregateFunctionContext(member, descriptor, implementationType, functionObjectName, generator)); }
public void Collect_Fails_On_Noncollection_Target() { CollectFunction fn = new CollectFunction(); MemberMappingDescriptor member = new MemberMappingDescriptor(); member.OwnerType = typeof(AttributedUserDTO); member.Type = typeof(string); member.Member = "FullName"; member.IsArray = false; member.IsList = false; member.Expression = "sum:$Projects/Tasks"; ClassMappingDescriptor desc = new ClassMappingDescriptor(); desc.SourceType = typeof(User); AggregateFunctionContext ctxt = new AggregateFunctionContext(member, desc, null, "", null); try { fn.GetInitializationStatements(ctxt); } catch (OtisException e) { if (e.Message.Contains("Target member 'FullName' for 'collect' aggregate function must be an array or a collection")) { return; // success } } Assert.Fail("Tested method didn't throw an exception!"); }
private ClassMappingDescriptor CreateClassDescriptor(XmlNode node) { ClassMappingDescriptor desc = new ClassMappingDescriptor(); desc.TargetType = Type.GetType(node.Attributes["name"].Value); // must exist if (desc.TargetType == null) { throw new OtisException(String.Format("Target Type \"{0}\" cannot be found", node.Attributes["name"].Value)); } // todo: check if types exist + test. desc.SourceType = Type.GetType(node.Attributes["source"].Value); // must exist if (desc.SourceType == null) { throw new OtisException(String.Format("Source Type \"{0}\" cannot be found", node.Attributes["source"].Value)); } desc.MappingHelper = GetAttributeValue(node.Attributes["helper"]); // optional if (desc.HasHelper) { desc.IsHelperStatic = desc.MappingHelper.Contains("."); } desc.MappingPreparer = GetAttributeValue(node.Attributes["preparer"]); // optional if (desc.HasPreparer) { desc.IsPreparerStatic = desc.MappingPreparer.Contains("."); } AddMemberDescriptors(desc, node); return(desc); }
private static string GetPath(ClassMappingDescriptor descriptor, MemberMappingDescriptor member) { // todo: optimize - don't do this for every member, this is also done in AggregateFunctionContext ctor IList <AggregateExpressionPathItem> pathItems = ExpressionParser.BuildAggregatePathItem(descriptor, member); bool isLastItemCollection = pathItems[pathItems.Count - 1].IsCollection; string path = member.Expression; int pos = path.IndexOf(':'); if (pos >= 0) { path = path.Substring(pos + 1); } if (!isLastItemCollection) { pos = path.LastIndexOf('/'); if (pos >= 0) { path = path.Substring(0, pos); } } return(path); }
public static IList <AggregateExpressionPathItem> BuildAggregatePathItem(ClassMappingDescriptor descriptor, MemberMappingDescriptor member) { string firstPart = member.AggregateMappingDescription.PathParts[0]; string targetName = firstPart.StartsWith("$") ? "source" : ""; List <AggregateExpressionPathItem> pathItems = new List <AggregateExpressionPathItem>(3); Type targetType = descriptor.SourceType; foreach (string pathPart in member.AggregateMappingDescription.PathParts) { if (pathPart.Contains(".")) { string[] subParts = pathPart.Split('.'); foreach (string subPart in subParts) { targetName = AddPathItems(member, pathItems, subPart, targetName, ref targetType); } } else { targetName = AddPathItems(member, pathItems, pathPart, targetName, ref targetType); } } return(pathItems); }
public CodeMemberMethod CreateToListMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); CreateExplicitInterfaceMethod(descriptor, method, "ToList"); method.ReturnType = new CodeTypeReference(string.Format("List<{0}>", TypeHelper.GetTypeDefinition(descriptor.TargetType))); method.Parameters.Add(new CodeParameterDeclarationExpression(string.Format("IEnumerable<{0}>", TypeHelper.GetTypeDefinition(descriptor.SourceType)), "source")); method.Statements.Add(Util.CreateNullHandlingStatement(false, true, true)); string listType = string.Format("List<{0}>", TypeHelper.GetTypeDefinition(descriptor.TargetType)); string listInit = string.Format("new {0}(10)", listType); method.Statements.Add(new CodeVariableDeclarationStatement(listType, "lst", new CodeSnippetExpression(listInit))); method.Statements.Add(new CodeVariableDeclarationStatement(GetInterfaceTypeName(descriptor), "_this", new CodeThisReferenceExpression())); string forEach = string.Format("foreach({0} srcItem in source){{ lst.Add(_this.AssembleFrom(srcItem)); }}", TypeHelper.GetTypeDefinition(descriptor.SourceType)); method.Statements.Add(new CodeSnippetExpression(forEach)); method.Statements.Add(Util.CreateReturnStatement("lst")); return(method); }
private CodeStatement CreateInitializationStatement(ClassMappingDescriptor descriptor) { string format = descriptor.TargetType.IsValueType ? "default ({0})" : "new {0}()"; string createSnippet = string.Format(format, TypeHelper.GetTypeDefinition(descriptor.TargetType)); return(new CodeVariableDeclarationStatement(descriptor.TargetType, "target", new CodeSnippetExpression(createSnippet))); }
private static CodeStatement[] CreateAggregateMappingStatements(ClassMappingDescriptor descriptor, ICollection<MemberMappingDescriptor> members, CodeGeneratorContext context) { /*if (!member.IsAggregateExpression) todo: remove throw new OtisException(string.Format("Expression '{0}' is not a aggregate expression", member.Expression)); */ AggregateExpressionBuilder expBuilder = new AggregateExpressionBuilder(descriptor, members, context.FunctionMap); return expBuilder.GetStatements(); }
public CodeMemberMethod CreateInPlaceTransformationMethodForValueTypes(ClassMappingDescriptor descriptor) { CodeMemberMethod method = CreateInPlaceTransformationMethod(descriptor); method.Parameters[0].Direction = FieldDirection.Ref; method.Parameters[1].Direction = FieldDirection.Ref; return method; }
private static void CheckDescription <Target, Source>(ClassMappingDescriptor desc) { Assert.AreEqual(typeof(Target), desc.TargetType); Assert.AreEqual(typeof(Source), desc.SourceType); Assert.AreEqual("Otis.Tests.Util.Convert", desc.MappingHelper); Assert.AreEqual(8, desc.MemberDescriptors.Count); MemberMappingDescriptor member = null; member = Helpers.FindMember(desc.MemberDescriptors, "Id"); Assert.AreEqual("$Id", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(int), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "Age"); Assert.AreEqual("$Age", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(int), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "UserName"); Assert.AreEqual("$UserName.ToUpper()", member.Expression); Assert.AreEqual("\"[unknown]\"", member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(string), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "FullName"); Assert.AreEqual("$FirstName + \" \" + $LastName", member.Expression); Assert.AreEqual("\"MISSING_NAME_PART\"", member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(string), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "Title"); Assert.AreEqual("\"Mr.\" + $FirstName + \" \" + $LastName", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(string), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "ProjectCount"); Assert.AreEqual("$Projects.Count", member.Expression); Assert.AreEqual(null, member.NullValue); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(int), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "Gender"); Assert.AreEqual(2, member.Projections.Count); Assert.AreEqual("Otis.Tests.Gender.Male", member.Projections["\"M\""]); Assert.AreEqual("Otis.Tests.Gender.Female", member.Projections["\"W\""]); Assert.AreEqual(typeof(Target), member.OwnerType); Assert.AreEqual(typeof(Otis.Tests.Gender), member.Type); member = Helpers.FindMember(desc.MemberDescriptors, "GenderCode"); Assert.AreEqual(2, member.Projections.Count); Assert.AreEqual("\"M\"", member.Projections["\"M\""]); Assert.AreEqual("\"W\"", member.Projections["\"W\""]); }
private static CodeStatement[] CreateAggregateMappingStatements(ClassMappingDescriptor descriptor, ICollection <MemberMappingDescriptor> members, CodeGeneratorContext context) { /*if (!member.IsAggregateExpression) todo: remove * throw new OtisException(string.Format("Expression '{0}' is not a aggregate expression", member.Expression)); */ AggregateExpressionBuilder expBuilder = new AggregateExpressionBuilder(descriptor, members, context.FunctionMap); return(expBuilder.GetStatements()); }
public void Formatting_Is_Detected_In_Assembly_Mapping() { IMappingDescriptorProvider provider = ProviderFactory.FromType(typeof(UserDTO)); ClassMappingDescriptor desc = provider.ClassDescriptors[0]; MemberMappingDescriptor member = Helpers.FindMember(desc.MemberDescriptors, "BirthDay"); Assert.IsTrue(member.HasFormatting); Assert.AreEqual("{0:D}", member.Format); }
public AggregateExpressionBuilder(ClassMappingDescriptor descriptor, ICollection <MemberMappingDescriptor> members, FunctionMap functionMap) { m_contexts = new List <AggregateFunctionContext>(members.Count); foreach (MemberMappingDescriptor member in members) { m_contexts.Add(CreateMemberContext(descriptor, member, functionMap)); } }
public AggregateExpressionBuilder(ClassMappingDescriptor descriptor, ICollection<MemberMappingDescriptor> members, FunctionMap functionMap) { m_contexts = new List<AggregateFunctionContext>(members.Count); foreach (MemberMappingDescriptor member in members) { m_contexts.Add(CreateMemberContext(descriptor, member, functionMap)); } }
public void Read_Mapping_From_Xml() { IMappingDescriptorProvider provider = ProviderFactory.FromXmlFile("XmlMappings\\mappings.xml"); Assert.AreEqual(2, provider.ClassDescriptors.Count); ClassMappingDescriptor desc = provider.ClassDescriptors[0]; CheckDescription <XmlUserDTO, User>(desc); }
public void Read_Mapping_From_Assembly() { IMappingDescriptorProvider provider = ProviderFactory.FromType(typeof(AttributedUserDTO)); Assert.AreEqual(1, provider.ClassDescriptors.Count); ClassMappingDescriptor desc = provider.ClassDescriptors[0]; CheckDescription <AttributedUserDTO, User>(desc); }
public CodeMemberMethod CreateInPlaceTransformationMethodForValueTypes(ClassMappingDescriptor descriptor) { CodeMemberMethod method = CreateInPlaceTransformationMethod(descriptor); method.Parameters[0].Direction = FieldDirection.Ref; method.Parameters[1].Direction = FieldDirection.Ref; return(method); }
private void AddMemberDescriptors(ClassMappingDescriptor desc, XmlNode classNode) { XmlNodeList members = classNode.SelectNodes("default:member", m_nsMgr); foreach (XmlNode memberNode in members) { desc.MemberDescriptors.Add(CreateMemberDescriptor(desc, memberNode)); } AddInheritanceMemberDescriptors(desc); }
public CodeMemberMethod CreateInPlaceTransformationMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); CreateMethodCommons(method, "Assemble", descriptor); method.ReturnType = new CodeTypeReference(typeof(void)); method.Parameters.Add(new CodeParameterDeclarationExpression(descriptor.TargetType, "target")); method.Parameters.Add(new CodeParameterDeclarationExpression(descriptor.SourceType, "source")); return method; }
public void Formatting_Is_Detected_In_Xml_Mapping() { IMappingDescriptorProvider provider = ProviderFactory.FromXmlFile("XmlMappings\\mappings.xml"); Assert.AreEqual(2, provider.ClassDescriptors.Count); ClassMappingDescriptor desc = provider.ClassDescriptors[1]; MemberMappingDescriptor member = Helpers.FindMember(desc.MemberDescriptors, "BirthDay"); Assert.IsTrue(member.HasFormatting); Assert.AreEqual("{0:D}", member.Format); }
public CodeMemberMethod CreateTypeTransformationMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); method.Statements.Add(CreateInitializationStatement(descriptor)); CreateMethodCommons(method, "AssembleFrom", descriptor); method.ReturnType = new CodeTypeReference(descriptor.TargetType); method.Parameters.Add(new CodeParameterDeclarationExpression(descriptor.SourceType, "source")); method.Statements.Add(Util.CreateReturnStatement("target")); return method; }
public CodeMemberMethod CreateInPlaceTransformationMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); CreateMethodCommons(method, "Assemble", descriptor); method.ReturnType = new CodeTypeReference(typeof(void)); method.Parameters.Add(new CodeParameterDeclarationExpression(descriptor.TargetType, "target")); method.Parameters.Add(new CodeParameterDeclarationExpression(descriptor.SourceType, "source")); return(method); }
private static void CreateExplicitInterfaceMethod(ClassMappingDescriptor descriptor, CodeMemberMethod method, string methodName) { method.Name = methodName; string interfaceType = GetInterfaceTypeName(descriptor); method.Attributes = MemberAttributes.Final; // interfaces are explicitly implemented which makes it possible to have multiple methods with // same name and same parameters in one class, e.g. // DTO1 AssembleFrom(Entity); -> implemented as: DTO1 IAssembler<DTO1, Entity>.AssembleFrom(Entity); // DTO2 AssembleFrom(Entity); -> implemented as: DTO2 IAssembler<DTO2, Entity>.AssembleFrom(Entity); method.PrivateImplementationType = new CodeTypeReference(interfaceType); }
public CodeMemberMethod CreateTypeTransformationMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); method.Statements.Add(CreateInitializationStatement(descriptor)); CreateMethodCommons(method, "AssembleFrom", descriptor); method.ReturnType = new CodeTypeReference(descriptor.TargetType); method.Parameters.Add(new CodeParameterDeclarationExpression(descriptor.SourceType, "source")); method.Statements.Add(Util.CreateReturnStatement("target")); return(method); }
public CodeMemberMethod CreateToArrayMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); CreateExplicitInterfaceMethod(descriptor, method, "ToArray"); method.ReturnType = new CodeTypeReference(string.Format("{0}[]", TypeHelper.GetTypeDefinition(descriptor.TargetType))); method.Parameters.Add(new CodeParameterDeclarationExpression(string.Format("IEnumerable<{0}>", TypeHelper.GetTypeDefinition(descriptor.SourceType)), "source")); method.Statements.Add(Util.CreateNullHandlingStatement(false, true, true)); method.Statements.Add(new CodeVariableDeclarationStatement(GetInterfaceTypeName(descriptor), "_this", new CodeThisReferenceExpression())); method.Statements.Add(Util.CreateReturnStatement("_this.ToList(source).ToArray()")); return method; }
public AggregateFunctionContext(MemberMappingDescriptor member, ClassMappingDescriptor descriptor, Type implementationType, string functionObjectName, IAggregateFunctionCodeGenerator generator) { m_member = member; m_generator = generator; m_functionObjectName = functionObjectName; m_implementationType = implementationType; m_descriptor = descriptor; m_pathItems = ExpressionParser.BuildAggregatePathItem(descriptor, member); m_sourceItem = m_pathItems[m_pathItems.Count - 1]; }
public CodeMemberMethod CreateToArrayMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); CreateExplicitInterfaceMethod(descriptor, method, "ToArray"); method.ReturnType = new CodeTypeReference(string.Format("{0}[]", TypeHelper.GetTypeDefinition(descriptor.TargetType))); method.Parameters.Add(new CodeParameterDeclarationExpression(string.Format("IEnumerable<{0}>", TypeHelper.GetTypeDefinition(descriptor.SourceType)), "source")); method.Statements.Add(Util.CreateNullHandlingStatement(false, true, true)); method.Statements.Add(new CodeVariableDeclarationStatement(GetInterfaceTypeName(descriptor), "_this", new CodeThisReferenceExpression())); method.Statements.Add(Util.CreateReturnStatement("_this.ToList(source).ToArray()")); return(method); }
public static CodeStatement[] CreateMappingStatements(ClassMappingDescriptor descriptor, CodeGeneratorContext context) { Dictionary <string, List <MemberMappingDescriptor> > aggregateGroups = new Dictionary <string, List <MemberMappingDescriptor> >(); List <CodeStatement> statements = new List <CodeStatement>(20); foreach (MemberMappingDescriptor member in descriptor.MemberDescriptors) { if (member.IsAggregateExpression) { // group all agregates by expression to avoid multiple traversals over same path //string path = GetPath(member.Expression); string path = GetPath(descriptor, member); if (!aggregateGroups.ContainsKey(path)) { aggregateGroups[path] = new List <MemberMappingDescriptor>(1); } aggregateGroups[path].Add(member); } else { CodeStatement[] st = CreateNonAggregateMappingStatements(descriptor, member, context); if (member.HasNullValue) { CodeStatement[] falseStatements = st; CodeStatement[] trueStatements = new CodeStatement[1]; trueStatements[0] = new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), new CodeSnippetExpression(member.NullValue.ToString())); string checkExpression = GetNullablePartsCheckExpression(member); CodeExpression ifExpression = new CodeSnippetExpression(checkExpression); st = new CodeStatement[1]; st[0] = new CodeConditionStatement(ifExpression, trueStatements, falseStatements); } statements.AddRange(st); } } foreach (List <MemberMappingDescriptor> group in aggregateGroups.Values) { CodeStatement[] st = CreateAggregateMappingStatements(descriptor, group, context); statements.AddRange(st); } return(statements.ToArray()); }
public static CodeStatement[] CreateMappingStatements(ClassMappingDescriptor descriptor, CodeGeneratorContext context) { Dictionary<string, List<MemberMappingDescriptor>> aggregateGroups = new Dictionary<string, List<MemberMappingDescriptor>>(); List<CodeStatement> statements = new List<CodeStatement>(20); foreach (MemberMappingDescriptor member in descriptor.MemberDescriptors) { if (member.IsAggregateExpression) { // group all agregates by expression to avoid multiple traversals over same path //string path = GetPath(member.Expression); string path = GetPath(descriptor, member); if(!aggregateGroups.ContainsKey(path)) aggregateGroups[path] = new List<MemberMappingDescriptor>(1); aggregateGroups[path].Add(member); } else { CodeStatement[] st = CreateNonAggregateMappingStatements(descriptor, member, context); if(member.HasNullValue) { CodeStatement[] falseStatements = st; CodeStatement[] trueStatements = new CodeStatement[1]; trueStatements[0] = new CodeAssignStatement( new CodeVariableReferenceExpression("target." + member.Member), new CodeSnippetExpression(member.NullValue.ToString())); string checkExpression = GetNullablePartsCheckExpression(member); CodeExpression ifExpression = new CodeSnippetExpression(checkExpression); st = new CodeStatement[1]; st[0] = new CodeConditionStatement(ifExpression, trueStatements, falseStatements); } statements.AddRange(st); } } foreach (List<MemberMappingDescriptor> group in aggregateGroups.Values) { CodeStatement[] st = CreateAggregateMappingStatements(descriptor, group, context); statements.AddRange(st); } return statements.ToArray(); }
private void AddInheritanceMemberDescriptors(ClassMappingDescriptor currentClassDescriptor) { foreach (ClassMappingDescriptor desc in m_classDescriptors) { if (desc.TargetType.Equals(currentClassDescriptor.TargetType)) { continue; } if (desc.TargetType.IsAssignableFrom(currentClassDescriptor.TargetType)) { CopyMemberDescriptors(desc, currentClassDescriptor); } if (currentClassDescriptor.TargetType.IsAssignableFrom(desc.TargetType)) { CopyMemberDescriptors(currentClassDescriptor, desc); } } }
private static void AddMemberDescriptors(ClassMappingDescriptor desc) { FieldInfo[] fields = desc.TargetType.GetFields(BindingFlags.Public | BindingFlags.Instance); PropertyInfo[] properties = desc.TargetType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in fields) { if (field.IsDefined(typeof(MapAttribute), false)) { desc.MemberDescriptors.Add(CreateMemberMapping(desc, field)); } } foreach (PropertyInfo property in properties) { if (property.IsDefined(typeof(MapAttribute), false)) { desc.MemberDescriptors.Add(CreateMemberMapping(desc, property)); } } }
public CodeMemberMethod CreateToListMethod(ClassMappingDescriptor descriptor) { CodeMemberMethod method = new CodeMemberMethod(); CreateExplicitInterfaceMethod(descriptor, method, "ToList"); method.ReturnType = new CodeTypeReference(string.Format("List<{0}>", TypeHelper.GetTypeDefinition(descriptor.TargetType))); method.Parameters.Add(new CodeParameterDeclarationExpression(string.Format("IEnumerable<{0}>", TypeHelper.GetTypeDefinition(descriptor.SourceType)), "source")); method.Statements.Add(Util.CreateNullHandlingStatement(false, true, true)); string listType = string.Format("List<{0}>", TypeHelper.GetTypeDefinition(descriptor.TargetType)); string listInit = string.Format("new {0}(10)", listType); method.Statements.Add(new CodeVariableDeclarationStatement(listType, "lst", new CodeSnippetExpression(listInit))); method.Statements.Add(new CodeVariableDeclarationStatement(GetInterfaceTypeName(descriptor), "_this", new CodeThisReferenceExpression())); string forEach = string.Format("foreach({0} srcItem in source){{ lst.Add(_this.AssembleFrom(srcItem)); }}", TypeHelper.GetTypeDefinition(descriptor.SourceType)); method.Statements.Add(new CodeSnippetExpression(forEach)); method.Statements.Add(Util.CreateReturnStatement("lst")); return method; }
private static void AddHelperMethod(ClassMappingDescriptor desc) { MethodInfo[] methods = desc.TargetType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (MethodInfo method in methods) if (method.IsDefined(typeof(MappingHelperAttribute), false)) { if(desc.HasHelper) { string msg = string.Format(errDuplicateHelper, method.Name, TypeHelper.GetTypeDefinition(desc.TargetType), desc.MappingHelper); throw new OtisException(msg); } if (!method.IsPublic) { string msg = string.Format(errHelperIsPrivate, method.Name, TypeHelper.GetTypeDefinition(desc.TargetType)); throw new OtisException(msg); } desc.MappingHelper = method.Name; desc.IsHelperStatic = method.IsStatic; } }
private MemberMappingDescriptor CreateMemberDescriptor(ClassMappingDescriptor classDesc, XmlNode node) { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.Member = GetAttributeValue(node.Attributes["name"]); desc.Expression = GetAttributeValue(node.Attributes["expression"], "$" + desc.Member); desc.NullValue = GetAttributeValue(node.Attributes["nullValue"]); desc.Format = GetAttributeValue(node.Attributes["format"]); desc.OwnerType = classDesc.TargetType; MemberInfo member = FindMember(classDesc.TargetType, desc.Member); if (member == null) { string msg = string.Format(Errors.MemberNotFound, desc.Member, TypeHelper.GetTypeDefinition(classDesc.TargetType)); throw new OtisException(msg); } desc.Type = GetTargetType(member); if (desc.HasFormatting && desc.Type != typeof(string)) { string msg = string.Format(Errors.FormattingAppliedOnNonStringMember, TypeHelper.GetTypeDefinition(classDesc.TargetType), desc.Member, TypeHelper.GetTypeDefinition(desc.Type)); throw new OtisException(msg); } desc.IsArray = desc.Type.IsArray; desc.IsList = (typeof(ICollection).IsAssignableFrom(desc.Type)) || desc.Type.GetInterface(typeof(ICollection <>).FullName) != null; XmlNodeList projections = node.SelectNodes("default:map", m_nsMgr); desc.Projections = BuildProjections(desc, projections); return(desc); }
public void AddMapping(ClassMappingDescriptor descriptor, CodeGeneratorContext context) { CodeMemberMethod methodAssembleFrom = m_generator.CreateTypeTransformationMethod(descriptor); m_assemblerClass.Members.Add(methodAssembleFrom); CodeMemberMethod methodAssemble = m_generator.CreateInPlaceTransformationMethod(descriptor); m_assemblerClass.Members.Add(methodAssemble); CodeMemberMethod methodAssembleValueType = m_generator.CreateInPlaceTransformationMethodForValueTypes(descriptor); m_assemblerClass.Members.Add(methodAssembleValueType); CodeMemberMethod methodToList = m_generator.CreateToListMethod(descriptor); m_assemblerClass.Members.Add(methodToList); CodeMemberMethod methodToArray = m_generator.CreateToArrayMethod(descriptor); m_assemblerClass.Members.Add(methodToArray); string interfaceType = string.Format( "IAssembler<{0}, {1}>", TypeHelper.GetTypeDefinition(descriptor.TargetType), TypeHelper.GetTypeDefinition(descriptor.SourceType)); m_assemblerClass.BaseTypes.Add(interfaceType); AddReferencedAssemblies(descriptor); }
private static CodeStatement[] CreateNonAggregateMappingStatements(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, CodeGeneratorContext context) { if (member.Projections.Count > 0) { return(CreateProjectionMapping(member)); } if (member.Type == typeof(string) || member.Type.IsPrimitive) { return(CreateSimpleMapping(member)); } if (member.IsArray) { return(CreateArrayMappingStatements(member)); } if (member.IsList) { return(CreateListMappingStatements(member)); } return(CreateAssemblerMapping(member)); }
private static void AddHelperMethod(ClassMappingDescriptor desc) { MethodInfo[] methods = desc.TargetType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (MethodInfo method in methods) { if (method.IsDefined(typeof(MappingHelperAttribute), false)) { if (desc.HasHelper) { string msg = string.Format(errDuplicateHelper, method.Name, TypeHelper.GetTypeDefinition(desc.TargetType), desc.MappingHelper); throw new OtisException(msg); } if (!method.IsPublic) { string msg = string.Format(errHelperIsPrivate, method.Name, TypeHelper.GetTypeDefinition(desc.TargetType)); throw new OtisException(msg); } desc.MappingHelper = method.Name; desc.IsHelperStatic = method.IsStatic; } } }
private CodeMemberMethod CreateMethodCommons(CodeMemberMethod method, string methodName, ClassMappingDescriptor descriptor) { CreateExplicitInterfaceMethod(descriptor, method, methodName); if (descriptor.HasPreparer) { method.Statements.Add(CreatePreparerCall(descriptor)); } CodeStatement[] statements = FunctionMappingGenerator.CreateMappingStatements(descriptor, m_context); method.Statements.AddRange(statements); if (descriptor.HasHelper) { method.Statements.Add(CreateHelperCall(descriptor)); } return method; }
private void AddInheritanceMemberDescriptors(ClassMappingDescriptor currentClassDescriptor) { foreach(ClassMappingDescriptor desc in m_classDescriptors) { if (desc.TargetType.Equals(currentClassDescriptor.TargetType)) continue; if (desc.TargetType.IsAssignableFrom(currentClassDescriptor.TargetType)) { CopyMemberDescriptors(desc, currentClassDescriptor); } if (currentClassDescriptor.TargetType.IsAssignableFrom(desc.TargetType)) { CopyMemberDescriptors(currentClassDescriptor, desc); } } }
private static void CopyMemberDescriptors(ClassMappingDescriptor from, ClassMappingDescriptor to) { foreach(MemberMappingDescriptor fromMember in from.MemberDescriptors) { // check if the member mapping is overriden in the derived class - do // not copy in that case bool overriden = false; foreach(MemberMappingDescriptor derivedMember in to.MemberDescriptors) { if (!fromMember.Member.Equals(derivedMember.Member)) continue; overriden = true; break; } if (overriden) continue; MemberMappingDescriptor toMember = new MemberMappingDescriptor(fromMember); toMember.OwnerType = to.TargetType; // check if the member is visible in the derived type MemberInfo member = FindMember(to.TargetType, toMember.Member); if (member != null) { to.MemberDescriptors.Add(toMember); } } }
private ClassMappingDescriptor CreateClassDescriptor(XmlNode node) { ClassMappingDescriptor desc = new ClassMappingDescriptor(); desc.TargetType = Type.GetType(node.Attributes["name"].Value); // must exist if (desc.TargetType == null) { throw new OtisException(String.Format("Target Type \"{0}\" cannot be found", node.Attributes["name"].Value)); } // todo: check if types exist + test. desc.SourceType = Type.GetType(node.Attributes["source"].Value); // must exist if (desc.SourceType == null) { throw new OtisException(String.Format("Source Type \"{0}\" cannot be found", node.Attributes["source"].Value)); } desc.MappingHelper = GetAttributeValue(node.Attributes["helper"]); // optional if (desc.HasHelper) desc.IsHelperStatic = desc.MappingHelper.Contains("."); desc.MappingPreparer = GetAttributeValue(node.Attributes["preparer"]); // optional if (desc.HasPreparer) desc.IsPreparerStatic = desc.MappingPreparer.Contains("."); AddMemberDescriptors(desc, node); return desc; }
private static ClassMappingDescriptor CreateMapping(Type type) { ClassMappingDescriptor desc = new ClassMappingDescriptor(); desc.TargetType = type; object[] attrs = type.GetCustomAttributes(typeof(MapClassAttribute), false); MapClassAttribute attr = (MapClassAttribute) attrs[0]; // todo: assert (should be exactly 1) desc.SourceType = attr.SourceType; desc.MappingHelper = attr.Helper; if (desc.HasHelper) desc.IsHelperStatic = desc.MappingHelper.Contains("."); // todo: smarter assumption desc.MappingPreparer = attr.Preparer; if (desc.HasPreparer) desc.IsPreparerStatic = desc.MappingPreparer.Contains("."); // todo: smarter assumption AddMemberDescriptors(desc); AddPreparerMethod(desc); AddHelperMethod(desc); return desc; }
private static string GetInterfaceTypeName(ClassMappingDescriptor descriptor) { return string.Format("IAssembler<{0}, {1}>", TypeHelper.GetTypeDefinition(descriptor.TargetType), TypeHelper.GetTypeDefinition(descriptor.SourceType)); }
private static void AddMemberDescriptors(ClassMappingDescriptor desc) { FieldInfo[] fields = desc.TargetType.GetFields(BindingFlags.Public | BindingFlags.Instance); PropertyInfo[] properties = desc.TargetType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in fields) if (field.IsDefined(typeof(MapAttribute), false)) desc.MemberDescriptors.Add(CreateMemberMapping(desc, field)); foreach (PropertyInfo property in properties) if (property.IsDefined(typeof(MapAttribute), false)) desc.MemberDescriptors.Add(CreateMemberMapping(desc, property)); }
private static MemberMappingDescriptor CreateMemberMapping(ClassMappingDescriptor classDesc, MemberInfo member) { MemberMappingDescriptor desc = new MemberMappingDescriptor(); object[] attrs = member.GetCustomAttributes(typeof(MapAttribute), false); MapAttribute attr = (MapAttribute) attrs[0]; // todo: assert (should be exactly 1) + test desc.Member = member.Name; desc.Expression = attr.Expression ?? "$" + desc.Member; if (attr.NullValue is string) desc.NullValue = "\"" + attr.NullValue.ToString().Trim('"') + "\""; else if(attr.NullValue != null) desc.NullValue = attr.NullValue.ToString(); else desc.NullValue = null; desc.Format = attr.Format; desc.OwnerType = classDesc.TargetType; if(member.MemberType == MemberTypes.Property) { PropertyInfo p = (PropertyInfo)member; desc.Type = p.PropertyType; } else { FieldInfo f = (FieldInfo)member; desc.Type = f.FieldType; } if(desc.HasFormatting && desc.Type != typeof(string)) { string msg = string.Format(Errors.FormattingAppliedOnNonStringMember, TypeHelper.GetTypeDefinition(classDesc.TargetType), desc.Member, TypeHelper.GetTypeDefinition(desc.Type)); throw new OtisException(msg); } if(desc.Type.IsArray) { desc.IsArray = true; } else if (typeof(ICollection).IsAssignableFrom(desc.Type) || desc.Type.GetInterface(typeof(ICollection<>).FullName) != null) { desc.IsList = true; } if(attr.HasProjection) { desc.Projections = GetProjections(desc, attr.Projection); } return desc; }
private static CodeStatement[] CreateNonAggregateMappingStatements(ClassMappingDescriptor descriptor, MemberMappingDescriptor member, CodeGeneratorContext context) { if (member.Projections.Count > 0) return CreateProjectionMapping(member); if (member.Type == typeof(string) || member.Type.IsPrimitive) return CreateSimpleMapping(member); if (member.IsArray) return CreateArrayMappingStatements(member); if (member.IsList) return CreateListMappingStatements(member); return CreateAssemblerMapping(member); }
private static string GetPath(ClassMappingDescriptor descriptor, MemberMappingDescriptor member) { // todo: optimize - don't do this for every member, this is also done in AggregateFunctionContext ctor IList<AggregateExpressionPathItem> pathItems = ExpressionParser.BuildAggregatePathItem(descriptor, member); bool isLastItemCollection = pathItems[pathItems.Count - 1].IsCollection; string path = member.Expression; int pos = path.IndexOf(':'); if (pos >= 0) path = path.Substring(pos + 1); if (!isLastItemCollection) { pos = path.LastIndexOf('/'); if (pos >= 0) path = path.Substring(0, pos); } return path; }
private void CheckDescriptor(ClassMappingDescriptor descriptor) { //throw new Exception("!"); }
private CodeStatement CreateInitializationStatement(ClassMappingDescriptor descriptor) { string format = descriptor.TargetType.IsValueType ? "default ({0})" : "new {0}()"; string createSnippet = string.Format(format, TypeHelper.GetTypeDefinition(descriptor.TargetType)); return new CodeVariableDeclarationStatement(descriptor.TargetType, "target", new CodeSnippetExpression(createSnippet)); }
private MemberMappingDescriptor CreateMemberDescriptor(ClassMappingDescriptor classDesc, XmlNode node) { MemberMappingDescriptor desc = new MemberMappingDescriptor(); desc.Member = GetAttributeValue(node.Attributes["name"]); desc.Expression = GetAttributeValue(node.Attributes["expression"], "$" + desc.Member); desc.NullValue = GetAttributeValue(node.Attributes["nullValue"]); desc.Format = GetAttributeValue(node.Attributes["format"]); desc.OwnerType = classDesc.TargetType; MemberInfo member = FindMember(classDesc.TargetType, desc.Member); if(member == null) { string msg = string.Format(Errors.MemberNotFound, desc.Member, TypeHelper.GetTypeDefinition(classDesc.TargetType)); throw new OtisException(msg); } desc.Type = GetTargetType(member); if(desc.HasFormatting && desc.Type != typeof(string)) { string msg = string.Format(Errors.FormattingAppliedOnNonStringMember, TypeHelper.GetTypeDefinition(classDesc.TargetType), desc.Member, TypeHelper.GetTypeDefinition(desc.Type)); throw new OtisException(msg); } desc.IsArray = desc.Type.IsArray; desc.IsList = (typeof (ICollection).IsAssignableFrom(desc.Type)) || desc.Type.GetInterface(typeof(ICollection<>).FullName) != null; XmlNodeList projections = node.SelectNodes("default:map", m_nsMgr); desc.Projections = BuildProjections(desc, projections); return desc; }
private static CodeExpression CreatePreparerCall(ClassMappingDescriptor descriptor) { return CreateSupportFunctionCall(descriptor.MappingPreparer, descriptor.IsPreparerStatic); }
private void AddReferencedAssemblies(ClassMappingDescriptor descriptor) { AddAssembliesForType(descriptor.TargetType); AddAssembliesForType(descriptor.SourceType); }