private void AddProperty(IPropertyBuildContext <TSubject> context, MethodInfo buildChildContextMethod, PropertyInfo d)
        {
            PropertyInfo descriptor   = d;
            Type         propertyType = descriptor.PropertyType;

            AssignmentPolicyAttribute assignmentPolicyAttribute = descriptor.GetAttribute <AssignmentPolicyAttribute>();

            NullableAttribute nullableAttribute = descriptor.GetAttribute <NullableAttribute>();
            bool nullable = nullableAttribute == null || nullableAttribute.IsNullable;

            AssignmentPolicy policy;

            if (assignmentPolicyAttribute != null && context.Policy == AssignmentPolicy.Default)
            {
                policy = assignmentPolicyAttribute.Policy;
            }
            else
            {
                policy = context.Policy == AssignmentPolicy.Default ? AssignmentPolicy.CreateNewInstance : context.Policy;
            }

            object childbuilder;
            object currentPropertyValue = descriptor.GetValue(context.CurrentInstance, null);

            if (currentPropertyValue == null && nullable)
            {
                //todo: make this dependent on yet-to-implement nullable attribute
                childbuilder = context.GetPropertyMapBuilder(propertyType, currentPropertyValue);
            }
            else
            {
                childbuilder = context.GetPropertyMapBuilder(currentPropertyValue);
            }

            string name = descriptor.GetDisplayName();

            if (childbuilder != null)
            {
                // Create the SetInstanceDelegate that uses the builders' CurrentInstance for the set operation
                Delegate setMemberInstanceDelegate;
                {
                    Type helperSetInstanceDelegateType = typeof(HelperSetInstanceDelegate <,>)
                                                         .MakeGenericType(propertyType, typeof(TSubject));
                    ConstructorInfo setterConstructorInfo = helperSetInstanceDelegateType
                                                            .GetConstructor(new[] { typeof(PropertyInfo), typeof(IPropertyBuildContext <TSubject>) });
                    object helperSetInstanceDelegateInstance = setterConstructorInfo
                                                               .Invoke(new object[] { descriptor, context });

                    MethodInfo method =
                        helperSetInstanceDelegateType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public |
                                                                 BindingFlags.Instance)[0];
                    setMemberInstanceDelegate =
                        Delegate.CreateDelegate(typeof(SetInstanceDelegate <>).MakeGenericType(propertyType),
                                                helperSetInstanceDelegateInstance, method);
                }

                // Create the SetInstanceDelegate that uses the builders' CurrentInstance for the set operation
                Delegate getMemberInstanceDelegate;
                {
                    Type helperInstanceDelegateType = typeof(HelperGetInstanceDelegate <,>)
                                                      .MakeGenericType(propertyType, typeof(TSubject));
                    ConstructorInfo getterConstructorInfo = helperInstanceDelegateType
                                                            .GetConstructor(new[] { typeof(PropertyInfo), typeof(IPropertyBuildContext <TSubject>) });
                    object helperGetInstanceDelegateInstance = getterConstructorInfo
                                                               .Invoke(new object[] { descriptor, context });

                    MethodInfo method =
                        helperInstanceDelegateType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public |
                                                              BindingFlags.Instance)[0];
                    getMemberInstanceDelegate =
                        Delegate.CreateDelegate(typeof(GetInstanceDelegate <>).MakeGenericType(propertyType),
                                                helperGetInstanceDelegateInstance, method);
                }
                object childContext = buildChildContextMethod.MakeGenericMethod(propertyType).Invoke(context,
                                                                                                     new object[]
                {
                    name,
                    getMemberInstanceDelegate
                    ,
                    setMemberInstanceDelegate
                    ,
                    policy
                });

                MethodInfo buildPropertyMapMethod =
                    typeof(IPropertyMapBuilder).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public |
                                                           BindingFlags.Instance)[0];

                buildPropertyMapMethod.MakeGenericMethod(propertyType).Invoke(childbuilder, new[] { childContext });
            }
            else
            {
                context.AddEntry(name, new ReflectionGetter <TSubject>(descriptor, context),
                                 new ReflectionSetter <TSubject>(descriptor, context));
            }
        }
        protected override void BuildPropertyMapImpl(IPropertyBuildContext <TSubject> builder)
        {
            MethodInfo[] infos = typeof(IPropertyBuildContext <>).MakeGenericType(typeof(TSubject)).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
            MethodInfo   buildChildContextMethod = null;

            foreach (MethodInfo info in infos)
            {
                if (info.IsGenericMethod && info.ReturnType.IsGenericType)
                {
                    buildChildContextMethod = info;
                    break;
                }
            }
            if (buildChildContextMethod == null)
            {
                throw new InvalidDataException("Method not found!");
            }

            TSubject instance = builder.CurrentInstance;

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(instance);

            foreach (PropertyDescriptor d  in properties)
            {
                PropertyDescriptor descriptor = d;

                AttributeBuilderAttribute mapAttribute =
                    (AttributeBuilderAttribute)descriptor.Attributes[typeof(AttributeBuilderAttribute)];
                if (mapAttribute != null && mapAttribute.Invisible)
                {
                    continue;
                }

                DisplayNameAttribute displayNameAttribute =
                    (DisplayNameAttribute)descriptor.Attributes[typeof(DisplayNameAttribute)];
                string propertyName;
                if (displayNameAttribute == null || displayNameAttribute.DisplayName.Length < 1)
                {
                    propertyName = descriptor.Name;
                }
                else
                {
                    propertyName = displayNameAttribute.DisplayName;
                }
                AssignmentPolicyAttribute assignmentPolicyAttribute =
                    (AssignmentPolicyAttribute)descriptor.Attributes[typeof(AssignmentPolicyAttribute)];
                Type propertyType = descriptor.PropertyType;

                NullableAttribute nullableAttribute = (NullableAttribute)descriptor.Attributes[typeof(NullableAttribute)];
                bool nullable = nullableAttribute == null || nullableAttribute.IsNullable;

                AssignmentPolicy policy;

                if (assignmentPolicyAttribute != null && builder.Policy == AssignmentPolicy.Default)
                {
                    policy = assignmentPolicyAttribute.Policy;
                }
                else
                {
                    policy = builder.Policy == AssignmentPolicy.Default ? AssignmentPolicy.ModifyInstance : builder.Policy;
                }

                object childbuilder;
                object currentPropertyValue = descriptor.GetValue(builder.CurrentInstance);

                if (currentPropertyValue == null && nullable)
                {
                    //todo: make this dependent on yet-to-implement nullable attribute
                    childbuilder = builder.GetPropertyMapBuilder(propertyType, currentPropertyValue);
                }
                else
                {
                    childbuilder = builder.GetPropertyMapBuilder(currentPropertyValue);
                }

                if (childbuilder != null)
                {
                    // Create the SetInstanceDelegate that uses the builders' CurrentInstance for the set operation
                    Delegate setMemberInstanceDelegate;
                    {
                        Type helperSetInstanceDelegateType = typeof(HelperSetInstanceDelegate <,>)
                                                             .MakeGenericType(propertyType, typeof(TSubject));
                        ConstructorInfo setterConstructorInfo = helperSetInstanceDelegateType
                                                                .GetConstructor(new Type[] { typeof(PropertyDescriptor), typeof(IPropertyBuildContext <TSubject>) });
                        object helperSetInstanceDelegateInstance = setterConstructorInfo
                                                                   .Invoke(new object[] { descriptor, builder });

                        MethodInfo method = helperSetInstanceDelegateType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)[0];
                        setMemberInstanceDelegate = Delegate.CreateDelegate(typeof(SetInstanceDelegate <>).MakeGenericType(propertyType),
                                                                            helperSetInstanceDelegateInstance, method);
                    }

                    // Create the SetInstanceDelegate that uses the builders' CurrentInstance for the set operation
                    Delegate getMemberInstanceDelegate;
                    {
                        Type helperInstanceDelegateType = typeof(HelperGetInstanceDelegate <,>)
                                                          .MakeGenericType(propertyType, typeof(TSubject));
                        ConstructorInfo getterConstructorInfo = helperInstanceDelegateType
                                                                .GetConstructor(new Type[] { typeof(PropertyDescriptor), typeof(IPropertyBuildContext <TSubject>) });
                        object helperGetInstanceDelegateInstance = getterConstructorInfo
                                                                   .Invoke(new object[] { descriptor, builder });

                        MethodInfo method = helperInstanceDelegateType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)[0];
                        getMemberInstanceDelegate = Delegate.CreateDelegate(typeof(GetInstanceDelegate <>).MakeGenericType(propertyType),
                                                                            helperGetInstanceDelegateInstance, method);
                    }
                    object childContext = buildChildContextMethod.MakeGenericMethod(propertyType).Invoke(builder,
                                                                                                         new object[] { propertyName, getMemberInstanceDelegate,
                                                                                                                        setMemberInstanceDelegate,
                                                                                                                        policy });

                    MethodInfo buildPropertyMapMethod = typeof(IPropertyMapBuilder).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public |
                                                                                               BindingFlags.Instance)[0];

                    buildPropertyMapMethod.MakeGenericMethod(propertyType).Invoke(childbuilder, new object[] { childContext });
                }
                else
                {
                    builder.AddEntry(propertyName, new ReflectionGetter <TSubject>(descriptor, builder),
                                     new ReflectionSetter <TSubject>(descriptor, builder));
                }
            }
        }