internal static property GetProperty(MemberInfo memberInfo, string prefix = "", Func <MemberInfo, bool> notNull = null)
        {
            if (memberInfo.IsReadOnlyProperty())
            {
                return(null);
            }
            if (memberInfo.DeclaringType.GetSettableFieldsAndProperties().Any(memberInfo.IsBackingFieldFor))
            {
                return(null);
            }

            notNull = notNull ?? (mi => !mi.IsNullable());
            var returnType = memberInfo.ReturnType();
            var type       = GetTypeForPropertyRules.Rules.Select(r => r(memberInfo)).FirstOrDefault(t => t != null);

            if (type == null || type == typeof(void))
            {
                return(null);                                      //not for mapping, this one
            }
            var property = new property()
            {
                name    = memberInfo.Name,
                access  = memberInfo.Access(),
                notnull = notNull(memberInfo),
            };

            property.column.Add(new column().Setup(memberInfo, columnPrefix: prefix, notnull: property.notnull));

            property.type1 = type.AssemblyQualifiedName;

            UniqueAttribute.SetUniqueProperties(memberInfo, property);

            //this if statement could be happily replaced by some nifty lookup table or something
            if (returnType == typeof(DateTimeOffset) || returnType == typeof(DateTimeOffset?))
            {
                property.type1 = "datetimeoffset";
            }
            if (returnType == typeof(DateTime) || returnType == typeof(DateTime?))
            {
                property.type1 = "UtcDateTime";
            }
            if (returnType.IsEnum)
            {
                property.type1 =
                    typeof(EnumStringType <>).MakeGenericType(returnType).AssemblyQualifiedName;
            }
            // check nullable enum
            if (returnType.IsGenericType &&
                returnType.GetGenericTypeDefinition() == typeof(Nullable <>) &&
                returnType.GetGenericArguments()[0].IsEnum)
            {
                property.type1 =
                    typeof(EnumStringType <>).MakeGenericType(returnType.GetGenericArguments()[0]).AssemblyQualifiedName;
            }
            return(property);
        }
Ejemplo n.º 2
0
        public void Apply(Type type, @class @class, IEnumerable <Type> entityTypes, hibernatemapping hbm)
        {
            var entityMembersOnType = type.GetFieldsAndProperties().Where(p => entityTypes.Contains(p.ReturnType())).ToArray();

            foreach (var memberInfo in entityMembersOnType)
            {
                var prefix             = ColumnNamePrefix(memberInfo);
                var entityClassElement = memberInfo.ReturnType().ClassElement(hbm);
                var manyToOne          = new manytoone()
                {
                    name   = memberInfo.Name.Sanitise(),
                    column = entityClassElement.id.column.Copy()
                             .Each(c => c.SetName(prefix + c.GetName()))
                             .Each(c => c.index   = null)
                             .Each(c => c.notnull = !memberInfo.IsNullable()).ToList(),
                    access = memberInfo.Access(),
                };
                manyToOne.foreignkey = "FK_" + @class.table.Trim('[', ']') + "_" +
                                       string.Join("_", manyToOne.column.Select(c => c.name.Trim("[]".ToCharArray()))) +
                                       "_to_" + memberInfo.ReturnType().Name.Sanitise();
                UniqueAttribute.SetUniqueProperties(memberInfo, manyToOne);

                @class.manytoone.Add(manyToOne);


                //if there is a manytoone, there is probably a set on the other object...
                var potentialCorrespondingCollections = memberInfo.ReturnType().GetAllMembers()
                                                        //... so we get the collections on the other type
                                                        .Where(p => setTypes.MakeGenericTypes(type).Any(t => t.IsAssignableFrom(p.ReturnType())));


                if (potentialCorrespondingCollections.Count() > 1)
                {
                    var att = memberInfo.GetCustomAttributes(typeof(ManyToOneHintAttribute), false).SingleOrDefault() as ManyToOneHintAttribute;
                    if (att != null)
                    {
                        potentialCorrespondingCollections =
                            potentialCorrespondingCollections.Where(p => p.Name == att.CorrespondingCollectionName);
                    }
                }
                if (potentialCorrespondingCollections.Count() > 1)
                {
                    throw new Exception("Meow! There is more than 1 collection that might be the inverse! You may need to add a ManyToOneHintAttribute so we know which one to use");
                }
                if (potentialCorrespondingCollections.Count() == 1)
                {
                    var correspondingCollection = potentialCorrespondingCollections.Single();

                    if (setTypes.MakeGenericTypes(type).Any(t => t.IsAssignableFrom(correspondingCollection.ReturnType())))
                    {
                        var set = new set()
                        {
                            name   = correspondingCollection.Name,
                            access = correspondingCollection.Access(),
                            key    = new key()
                            {
                                column1    = manyToOne.column.Single().name,
                                foreignkey = "FK_" + @class.table.Trim('[', ']') + "_" + string.Join("_", manyToOne.column.Select(c => c.name.Trim("[]".ToCharArray()))) + "_to_" + memberInfo.ReturnType().ClassElement(hbm).table,
                                notnull    = false                     // so inverse works!memberInfo.IsNullable(),
                            },
                            inverse   = true,
                            onetomany = new onetomany()
                            {
                                @class = type.AssemblyQualifiedName
                            },
                            cascade = "all",
                        };
                        manyToOne.column.Each(c => c.notnull = false).ToArray();
                        var otherClassMap = memberInfo.ReturnType().ClassElement(hbm);

                        otherClassMap.set.Add(set);
                    }
                }
            }
        }