Example #1
0
        private static MethodDescription[] GetSerializationCallbacks(Type type,
                                                                     IDictionary <string, TypeDescription>
                                                                     typesByAssemblyQualifiedName)
        {
            var attributes   = new HashSet <SpecialMethod>();
            var methods      = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            var descriptions = new List <MethodDescription>();

            foreach (var method in methods)
            {
                var attribute = method.GetCustomAttribute <SerializationMethodAttribute>();
                if (attribute != null)
                {
                    var methodType = attribute.Method;
                    if (attributes.Contains(methodType))
                    {
                        throw new ArgumentException(
                                  string.Format(
                                      "The type '{0}.{1}' contains too many methods with the [{2}] attribute: There may not be more than one",
                                      type.Namespace, type.Name, methodType));
                    }
                    attributes.Add(methodType);
                    var description = MethodDescription.Create(method, typesByAssemblyQualifiedName);
                    descriptions.Add(description);
                }
            }
            return(descriptions.ToArray());
        }
 /// <summary>
 ///     Creates a new description for the given property.
 /// </summary>
 /// <param name="declaringType"></param>
 /// <param name="property"></param>
 /// <param name="typesByAssemblyQualifiedName"></param>
 /// <returns></returns>
 public static PropertyDescription Create(TypeDescription declaringType, PropertyInfo property, IDictionary <string, TypeDescription> typesByAssemblyQualifiedName)
 {
     return(new PropertyDescription(declaringType, property)
     {
         Name = property.Name,
         PropertyType = SharpRemote.TypeDescription.GetOrCreate(property.PropertyType, typesByAssemblyQualifiedName),
         GetMethod = property.GetMethod != null?MethodDescription.Create(property.GetMethod, typesByAssemblyQualifiedName) : null,
                         SetMethod = property.SetMethod != null?MethodDescription.Create(property.SetMethod, typesByAssemblyQualifiedName) : null
     });
 }
Example #3
0
        internal IEnumerable <ITypeModelDifference> FindDifferences(MethodDescription actualMethod)
        {
            var differences = new List <ITypeModelDifference>();

            differences.AddRange(ReturnParameter.FindDifferences(actualMethod.ReturnParameter));
            if (Parameters.Length != actualMethod.Parameters.Length)
            {
                differences.Add(new ParameterCountMismatch(this, actualMethod));
            }
            else
            {
                for (int i = 0; i < Parameters.Length; ++i)
                {
                    var expectedParameter = Parameters[i];
                    var actualParameter   = actualMethod.Parameters[i];
                    differences.AddRange(expectedParameter.FindDifferences(actualParameter));
                }
            }
            return(differences);
        }
Example #4
0
        /// <summary>
        /// </summary>
        /// <param name="methodInfo"></param>
        /// <param name="typesByAssemblyQualifiedName"></param>
        /// <returns></returns>
        public static MethodDescription Create(MethodInfo methodInfo,
                                               IDictionary <string, TypeDescription> typesByAssemblyQualifiedName)
        {
            var description = new MethodDescription(methodInfo)
            {
                ReturnParameter = ParameterDescription.Create(methodInfo.ReturnParameter, typesByAssemblyQualifiedName),
            };
            var parameters = methodInfo.GetParameters();

            if (parameters.Length > 0)
            {
                description.Parameters =
                    parameters.Select(x => ParameterDescription.Create(x, typesByAssemblyQualifiedName)).ToArray();
            }
            else
            {
                description.Parameters = EmptyParameters;
            }

            return(description);
        }
Example #5
0
        /// <summary>
        ///     Creates a new description for the given type.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="typesByAssemblyQualifiedName"></param>
        /// <param name="assumeByReference"></param>
        /// <returns></returns>
        public static TypeDescription Create(Type type,
                                             IDictionary <string, TypeDescription> typesByAssemblyQualifiedName,
                                             bool assumeByReference = false)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var assemblyQualifiedName = type.AssemblyQualifiedName;

            if (assemblyQualifiedName == null)
            {
                throw new ArgumentException("Type.AssemblyQualifiedName should not be null");
            }

            bool       builtIn, isEnumerable;
            MethodInfo singletonAccessor;
            Type       byReferenceInterface;
            var        serializerType = GetSerializationType(type,
                                                             assumeByReference,
                                                             out builtIn,
                                                             out isEnumerable,
                                                             out singletonAccessor,
                                                             out byReferenceInterface);

            var description = new TypeDescription(type, byReferenceInterface)
            {
                AssemblyQualifiedName = assemblyQualifiedName,
                SerializationType     = serializerType
            };

            typesByAssemblyQualifiedName.Add(assemblyQualifiedName, description);

            var serializationCallbacks = GetSerializationCallbacks(type, typesByAssemblyQualifiedName);

            switch (description.SerializationType)
            {
            case SerializationType.ByValue:
                description.Fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
                                     .Where(x => x.GetCustomAttribute <DataMemberAttribute>() != null)
                                     .Select(x => FieldDescription.Create(x, typesByAssemblyQualifiedName)).ToArray();
                description.Properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                                         .Where(x => x.GetCustomAttribute <DataMemberAttribute>() != null)
                                         .Select(x => PropertyDescription.Create(description, x, typesByAssemblyQualifiedName)).ToArray();
                description.Methods = serializationCallbacks;
                break;

            case SerializationType.ByReference:
                if (serializationCallbacks.Any())
                {
                    throw new ArgumentException(
                              string.Format(
                                  "The type '{0}.{1}' is marked with the [ByReference] attribute and thus may not contain serialization callback methods",
                                  type.Namespace, type.Name));
                }

                description.Fields     = new FieldDescription[0];
                description.Properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                         .Select(x => PropertyDescription.Create(description, x, typesByAssemblyQualifiedName)).ToArray();
                description.Methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                                      .Where(x => !x.IsSpecialName)
                                      .Select(x => MethodDescription.Create(x, typesByAssemblyQualifiedName)).ToArray();
                break;

            case SerializationType.Singleton:
                if (serializationCallbacks.Any())
                {
                    throw new ArgumentException(
                              string.Format(
                                  "The type '{0}.{1}' is a singleton and thus may not contain any serialization callbacks",
                                  type.Namespace, type.Name));
                }

                description.Fields     = new FieldDescription[0];
                description.Properties = new PropertyDescription[0];
                description.Methods    = new[] { MethodDescription.Create(singletonAccessor, typesByAssemblyQualifiedName) };
                break;

            case SerializationType.Unknown:
                description.Fields     = new FieldDescription[0];
                description.Properties = new PropertyDescription[0];
                description.Methods    = new MethodDescription[0];
                break;

            case SerializationType.NotSerializable:
                // TODO: Throw proper exception with proper error message
                throw new NotImplementedException();

            default:
                throw new NotImplementedException();
            }

            if (IsInterestingBaseType(type.BaseType))
            {
                description.BaseType = GetOrCreate(type.BaseType, typesByAssemblyQualifiedName);
            }
            description.IsBuiltIn     = builtIn;
            description.IsValueType   = type.IsValueType;
            description.IsClass       = type.IsClass;
            description.IsInterface   = type.IsInterface;
            description.IsEnum        = type.IsEnum;
            description.IsEnumerable  = isEnumerable;
            description.IsSealed      = type.IsSealed;
            description.IsGenericType = type.IsGenericType;

            if (type.IsGenericType)
            {
                var genericArguments = type.GetGenericArguments();
                var types            = new TypeDescription[genericArguments.Length];
                for (int i = 0; i < genericArguments.Length; ++i)
                {
                    types[i] = GetOrCreate(genericArguments[i], typesByAssemblyQualifiedName);
                }

                description.GenericArguments = types;
            }
            else if (type.IsArray)
            {
                description.GenericArguments = new[]
                {
                    GetOrCreate(type.GetElementType(), typesByAssemblyQualifiedName)
                };
            }
            else
            {
                description.GenericArguments = new TypeDescription[0];
            }

            if (type.IsEnum)
            {
                var storageType = Enum.GetUnderlyingType(type);
                description.StorageType = GetOrCreate(storageType, typesByAssemblyQualifiedName);

                var values       = Enum.GetValues(type).OfType <object>().ToArray();
                var names        = Enum.GetNames(type);
                var descriptions = new EnumValueDescription[values.Length];
                for (int i = 0; i < names.Length; ++i)
                {
                    descriptions[i] = EnumValueDescription.Create(storageType, values[i], names[i]);
                }

                description.EnumValues = descriptions;
            }

            return(description);
        }