Example #1
0
        /// <summary>
        /// Builds a mapping of member name to field/property
        /// </summary>
        /// <param name="objectType"></param>
        private IEnumerable <DataName> BuildMap(Type objectType, out IDictionary <string, MemberMap> maps)
        {
            bool hasName = false;
            IEnumerable <DataName> typeNames = this.Strategy.GetName(objectType);

            if (typeNames != null)
            {
                foreach (DataName typeName in typeNames)
                {
                    if (!typeName.IsEmpty)
                    {
                        hasName = true;
                        break;
                    }
                }
            }
            if (!hasName)
            {
                typeNames = new [] { new DataName(objectType) };
            }

            if (objectType.IsEnum)
            {
                // create special maps for enum types
                IDictionary <Enum, string> enumMap;
                maps = this.BuildEnumMap(objectType, out enumMap);
                return(typeNames);
            }

            // do not incurr the cost of member map for dictionaries
            if (typeof(IDictionary <string, object>).IsAssignableFrom(objectType) ||
                typeof(IDictionary).IsAssignableFrom(objectType))
            {
#if SILVERLIGHT && (NET20 || NET30 || NET35)
                lock (this.MemberCache)
                    lock (this.NameCache)
#elif NET20 || NET30
                this.MapLock.AcquireWriterLock(ResolverCache.LockTimeout);
#elif NET35
                this.MapLock.EnterWriteLock();
#endif
#if !NET40
                        try
#endif
                    {
                        // store marker in cache for future lookups
                        maps = (this.MemberCache[objectType] = null);
                        return(this.NameCache[objectType] = typeNames);
                    }
#if !NET40
                finally
#endif
                {
#if SILVERLIGHT && (NET20 || NET30 || NET35)
                    // noop
#elif NET20 || NET30
                    this.MapLock.ReleaseWriterLock();
#elif NET35
                    this.MapLock.ExitWriteLock();
#endif
                }
            }

            // create new mapping
            maps = new Dictionary <string, MemberMap>();

            bool isImmutableType = FactoryMap.IsImmutableType(objectType);

            // load properties into property map
            foreach (PropertyInfo info in objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy))
            {
                // Ignore indexer properties as aren't serialized
                // https://bugzilla.xamarin.com/show_bug.cgi?id=6821#c5
                if (info.GetIndexParameters().Length != 0 ||
                    this.Strategy.IsPropertyIgnored(info, isImmutableType))
                {
                    continue;
                }

                IEnumerable <DataName> names = this.Strategy.GetName(info);
                hasName = false;
                if (names != null)
                {
                    foreach (DataName name in names)
                    {
                        if (!name.IsEmpty)
                        {
                            hasName = true;
                            break;
                        }
                    }
                }
                if (!hasName)
                {
                    names = new[] { new DataName(info.Name) };
                }

                ValueIgnoredDelegate isIgnored = this.Strategy.GetValueIgnoredCallback(info);
                MemberMap            map       = null;

                foreach (DataName name in names)
                {
                    if (name.IsEmpty || maps.ContainsKey(name.LocalName))
                    {
                        continue;
                    }

                    if (map == null)
                    {
                        maps[name.LocalName] = map = new MemberMap(info, name, isIgnored);
                    }
                    else
                    {
                        maps[name.LocalName] = new MemberMap(map, name);
                    }
                }
            }

            // load fields into property map
            foreach (FieldInfo info in objectType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy))
            {
                if (this.Strategy.IsFieldIgnored(info))
                {
                    continue;
                }

                IEnumerable <DataName> names = this.Strategy.GetName(info);
                hasName = false;
                if (names != null)
                {
                    foreach (DataName name in names)
                    {
                        if (!name.IsEmpty)
                        {
                            hasName = true;
                            break;
                        }
                    }
                }
                if (!hasName)
                {
                    names = new[] { new DataName(info.Name) };
                }

                ValueIgnoredDelegate isIgnored = this.Strategy.GetValueIgnoredCallback(info);
                MemberMap            map       = null;

                foreach (DataName name in names)
                {
                    if (name.IsEmpty || maps.ContainsKey(name.LocalName))
                    {
                        continue;
                    }

                    if (map == null)
                    {
                        maps[name.LocalName] = map = new MemberMap(info, name, isIgnored);
                    }
                    else
                    {
                        maps[name.LocalName] = new MemberMap(map, name);
                    }
                }
            }

#if SILVERLIGHT && (NET20 || NET30 || NET35)
            lock (this.MemberCache)
                lock (this.NameCache)
#elif NET20 || NET30
            this.MapLock.AcquireWriterLock(ResolverCache.LockTimeout);
#elif NET35
            this.MapLock.EnterWriteLock();
#endif
#if !NET40
                    try
#endif
                {
                    // store in cache for future requests
                    this.MemberCache[objectType] = maps;
                    return(this.NameCache[objectType] = typeNames);
                }
#if !NET40
            finally
#endif
            {
#if SILVERLIGHT && (NET20 || NET30 || NET35)
                // noop
#elif NET20 || NET30
                this.MapLock.ReleaseWriterLock();
#elif NET35
                this.MapLock.ExitWriteLock();
#endif
            }
        }
Example #2
0
        public FactoryMap LoadFactory(Type type)
        {
            if (type == null || type == typeof(object))
            {
                return(null);
            }

            FactoryMap map;

#if SILVERLIGHT && (NET20 || NET30 || NET35)
            lock (this.Factories)
#elif NET20 || NET30
            this.FactoryLock.AcquireReaderLock(ResolverCache.LockTimeout);
#elif NET35
            this.FactoryLock.EnterReadLock();
#endif
#if !NET40
                try
#endif
            {
                if (this.Factories.TryGetValue(type, out map))
                {
                    return(map);
                }
            }
#if !NET40
            finally
#endif
            {
#if SILVERLIGHT && (NET20 || NET30 || NET35)
                // noop
#elif NET20 || NET30
                this.FactoryLock.ReleaseReaderLock();
#elif NET35
                this.FactoryLock.ExitReadLock();
#endif
            }

            map = new FactoryMap(type);

#if SILVERLIGHT && (NET20 || NET30 || NET35)
            lock (this.Factories)
#elif NET20 || NET30
            this.FactoryLock.AcquireWriterLock(ResolverCache.LockTimeout);
#elif NET35
            this.FactoryLock.EnterWriteLock();
#endif
#if !NET40
                try
#endif
            {
                // store in cache for future requests
                return(this.Factories[type] = map);
            }
#if !NET40
            finally
#endif
            {
#if SILVERLIGHT && (NET20 || NET30 || NET35)
                // noop
#elif NET20 || NET30
                this.FactoryLock.ReleaseWriterLock();
#elif NET35
                this.FactoryLock.ExitWriteLock();
#endif
            }
        }
Example #3
0
        /// <summary>
        /// Ctor
        /// </summary>
        public FactoryMap(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (FactoryMap.IsInvalidType(type))
            {
                throw new TypeLoadException(String.Format(
                                                FactoryMap.ErrorCannotInstantiate,
                                                type.FullName));
            }

            this.Ctor = DynamicMethodGenerator.GetTypeFactory(type);

            ConstructorInfo[] ctors;
            if (!typeof(IEnumerable).IsAssignableFrom(type))
            {
                if (this.Ctor != null)
                {
                    return;
                }

                ctors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                if (ctors.Length == 1)
                {
                    ConstructorInfo ctor = ctors[0];
                    this.Ctor     = DynamicMethodGenerator.GetTypeFactory(ctor);
                    this.CtorArgs = ctor.GetParameters();
                }
                return;
            }

            // many ICollection types take an IEnumerable or ICollection
            // as a constructor argument.  look through constructors for
            // a compatible match.
            ctors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);

            this.CollectionCtors = new Dictionary <Type, FactoryDelegate>(ctors.Length);

            foreach (ConstructorInfo ctor in ctors)
            {
                ParameterInfo[] paramList = ctor.GetParameters();
                if (paramList.Length != 1)
                {
                    continue;
                }

                Type argType = paramList[0].ParameterType;
                if ((argType == typeof(string)) ||
                    (
#if !NETCF
                        (argType.GetInterface(TypeCoercionUtility.TypeGenericIEnumerable, false) == null) &&
#endif
                        (typeof(IEnumerable).IsAssignableFrom(argType))))
                {
                    continue;
                }

                // save all constructors that can take an enumerable of objects
                this.CollectionCtors[argType] = DynamicMethodGenerator.GetTypeFactory(ctor);
            }

            if (this.Ctor == null)
            {
                // try to grab a private ctor if exists
                this.Ctor = DynamicMethodGenerator.GetTypeFactory(type);
            }

            // many collection types have an AddRange method
            // which adds a collection of items at once
            MethodInfo methodInfo = type.GetMethod("AddRange");
            if (methodInfo != null)
            {
                ParameterInfo[] parameters = methodInfo.GetParameters();
                if (parameters.Length == 1)
                {
                    this.AddRange     = DynamicMethodGenerator.GetMethodProxy(methodInfo);
                    this.AddRangeType = parameters[0].ParameterType;
                }
            }

            // many collection types have an Add method
            // which adds items one at a time
            Type collectionType = null;
#if !NETCF
            collectionType = type.GetInterface(TypeCoercionUtility.TypeGenericICollection, false);
#endif
            if (collectionType != null)
            {
                methodInfo = collectionType.GetMethod("Add");
            }
            else
            {
                methodInfo = type.GetMethod("Add");
            }

            if (methodInfo != null)
            {
                ParameterInfo[] parameters = methodInfo.GetParameters();
                if (parameters.Length == 1)
                {
                    this.Add     = DynamicMethodGenerator.GetMethodProxy(methodInfo);
                    this.AddType = parameters[0].ParameterType;
                }
            }
        }