internal static ObjectCreateInfo MakeSelectInfo(Type type) { lock (_selectedTypeInfo) { ObjectCreateInfo info; if (_selectedTypeInfo.TryGetValue(type, out info)) return info; info = new ObjectCreateInfo(type.GetPropertiesEx().Select(e=> new ObjectCreateMemberInfo(e.Name, null)), null); _selectedTypeInfo[type] = info; return info; } }
private void AddTypeMembers(Type type, XmlSerializerTypeInfo serializerTypeInfo) { var typesToCheck = new List<Type>(); var isModelBase = type.IsModelBase(); if (isModelBase) { // No need to check members, they will be serialized by ModelBase //var catelTypeInfo = PropertyDataManager.Default.GetCatelTypeInfo(type); //var modelBaseProperties = catelTypeInfo.GetCatelProperties(); //foreach (var modelBaseProperty in modelBaseProperties) //{ // typesToCheck.Add(modelBaseProperty.Value.Type); //} } else { var allowNonPublicReflection = AllowNonPublicReflection(type); // Fields var fields = type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var field in fields) { typesToCheck.Add(field.FieldType); } // Properties var properties = type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var property in properties) { typesToCheck.Add(property.PropertyType); } } foreach (var typeToCheck in typesToCheck) { if (serializerTypeInfo.IsTypeAlreadyHandled(typeToCheck)) { continue; } if (!IsTypeSerializable(typeToCheck, serializerTypeInfo)) { serializerTypeInfo.AddTypeAsHandled(typeToCheck); continue; } var propertyTypeFullName = typeToCheck.GetSafeFullName(); if (propertyTypeFullName == null) { serializerTypeInfo.AddTypeAsHandled(typeToCheck); continue; } GetKnownTypes(typeToCheck, serializerTypeInfo); } }
/// <summary> /// Initializes the view model meta data. /// <para /> /// This method only initializes the meta data once per view model type. If a type is already initialized, /// this method will immediately return. /// </summary> /// <param name="viewModelType">Type of the view model.</param> /// <returns>ViewModelMetadata.</returns> /// <exception cref="ArgumentNullException">The <paramref name="viewModelType" /> is <c>null</c>.</exception> private static ViewModelMetadata InitializeViewModelMetaData(Type viewModelType) { if (_metaData.ContainsKey(viewModelType)) { return _metaData[viewModelType]; } var properties = new List<PropertyInfo>(); var bindingFlags = BindingFlagsHelper.GetFinalBindingFlags(true, false, true); properties.AddRange(viewModelType.GetPropertiesEx(bindingFlags)); var modelObjectsInfo = new Dictionary<string, ModelInfo>(); var viewModelToModelMap = new Dictionary<string, ViewModelToModelMapping>(); var validationSummaries = new Dictionary<string, ValidationToViewModelAttribute>(); var modelNames = (from propertyInfo in properties where propertyInfo.IsDecoratedWithAttribute<ModelAttribute>() select propertyInfo.Name).ToList(); foreach (var propertyInfo in properties) { #region Model attributes var modelAttribute = propertyInfo.GetCustomAttributeEx(typeof(ModelAttribute), true) as ModelAttribute; if (modelAttribute != null) { modelObjectsInfo.Add(propertyInfo.Name, new ModelInfo(propertyInfo.Name, modelAttribute)); } #endregion #region ViewModelToModel attributes var viewModelToModelAttribute = propertyInfo.GetCustomAttributeEx(typeof(ViewModelToModelAttribute), true) as ViewModelToModelAttribute; if (viewModelToModelAttribute != null) { if (string.IsNullOrEmpty(viewModelToModelAttribute.Property)) { // Assume the property name in the model is the same as in the view model viewModelToModelAttribute.Property = propertyInfo.Name; } if (string.IsNullOrWhiteSpace(viewModelToModelAttribute.Model)) { Log.Debug("ViewToViewModel is missing the Model name, searching for the right model automatically"); if (modelNames.Count != 1) { throw Log.ErrorAndCreateException<InvalidOperationException>("It is only possible to automatically select the right model if there is 1 model. There are '{0}' models, so please specify the model name explicitly.", modelNames.Count); } viewModelToModelAttribute.Model = modelNames[0]; } if (!viewModelToModelMap.ContainsKey(propertyInfo.Name)) { viewModelToModelMap.Add(propertyInfo.Name, new ViewModelToModelMapping(propertyInfo.Name, viewModelToModelAttribute)); } } #endregion #region ValidationToViewModel attributes var validationToViewModelAttribute = propertyInfo.GetCustomAttributeEx(typeof(ValidationToViewModelAttribute), true) as ValidationToViewModelAttribute; if (validationToViewModelAttribute != null) { if (propertyInfo.PropertyType != typeof(IValidationSummary)) { throw Log.ErrorAndCreateException<InvalidOperationException>("A property decorated with the ValidationToViewModel attribute must be of type IValidationSummary, but '{0}' is not", propertyInfo.Name); } validationSummaries.Add(propertyInfo.Name, validationToViewModelAttribute); Log.Debug("Registered property '{0}' as validation summary", propertyInfo.Name); } #endregion } _metaData.Add(viewModelType, new ViewModelMetadata(viewModelType, modelObjectsInfo, viewModelToModelMap, validationSummaries)); return _metaData[viewModelType]; }
/// <summary> /// Finds the properties that represent a <see cref="PropertyData"/>. /// </summary> /// <param name="type">The type.</param> /// <returns>The list of <see cref="PropertyData"/> elements found as properties.</returns> /// <exception cref="InvalidOperationException">One ore more properties are not declared correctly.</exception> private static IEnumerable<PropertyData> FindCatelProperties(Type type) { // Properties - safety checks for non-static properties var nonStaticProperties = (from property in type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(true, false, true)) where property.PropertyType == typeof(PropertyData) select property).ToList(); foreach (var nonStaticProperty in nonStaticProperties) { string error = string.Format("The property '{0}' of type 'PropertyData' declared as instance, but they can only be used as static", nonStaticProperty.Name); Log.Error(error); throw new InvalidOperationException(error); } // Properties - safety checks for non-public fields var nonPublicProperties = (from property in type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(true, true, true)) where property.PropertyType == typeof(PropertyData) && !property.CanRead select property).ToList(); foreach (var nonPublicProperty in nonPublicProperties) { string error = string.Format("The property '{0}' of type 'PropertyData' declared as non-public, but they can only be used as public", nonPublicProperty.Name); Log.Error(error); throw new InvalidOperationException(error); } // Properties - actual addition var foundProperties = new List<PropertyData>(); var properties = new List<PropertyInfo>(); properties.AddRange(type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(true, true, false))); foreach (var property in properties) { if (property.PropertyType == typeof(PropertyData)) { var propertyValue = property.GetValue(null, null) as PropertyData; if (propertyValue != null) { foundProperties.Add(propertyValue); } } } return foundProperties; }
/// <summary> /// Finds the non catel properties. /// </summary> /// <param name="type">The type.</param> /// <returns>The list of <see cref="PropertyInfo"/> elements found as properties.</returns> private static IEnumerable<PropertyInfo> FindNonCatelProperties(Type type) { return (from property in type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(true, false, true)) where property.PropertyType != typeof(PropertyData) select property).ToList(); }
private void AddTypeMembers(Type type, XmlSerializerTypeInfo serializerTypeInfo) { var isModelBase = (type == typeof(ModelBase)) || typeof(ModelBase).IsAssignableFromEx(type); if (isModelBase) { var catelTypeInfo = PropertyDataManager.Default.GetCatelTypeInfo(type); var modelBaseProperties = catelTypeInfo.GetCatelProperties(); foreach (var modelBaseProperty in modelBaseProperties) { var propertyType = modelBaseProperty.Value.Type; if (propertyType.FullName != null) { GetKnownTypes(propertyType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(propertyType); } } } else { bool allowNonPublicReflection = AllowNonPublicReflection(type); // Fields var fields = type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var field in fields) { var fieldType = field.FieldType; if (fieldType.FullName != null) { GetKnownTypes(fieldType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(fieldType); } } // Properties var properties = type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false, allowNonPublicReflection)); foreach (var property in properties) { var propertyType = property.PropertyType; if (propertyType.FullName != null) { GetKnownTypes(propertyType, serializerTypeInfo); } else { serializerTypeInfo.AddTypeAsHandled(propertyType); } } } }
/// <summary> /// Gets the properties to serialize for the specified object. /// </summary> /// <param name="type">The type.</param> /// <returns>The list of properties to serialize.</returns> /// <exception cref="ArgumentNullException">The <paramref name="type"/> is <c>null</c>.</exception> public virtual HashSet<string> GetPropertiesToSerialize(Type type) { Argument.IsNotNull("type", type); return _propertiesToSerializeCache.GetFromCacheOrFetch(type, () => { var properties = new List<string>(); var propertyDataManager = PropertyDataManager.Default; var catelTypeInfo = propertyDataManager.GetCatelTypeInfo(type); var catelProperties = catelTypeInfo.GetCatelProperties(); var catelPropertyNames = catelProperties.Keys.ToList(); foreach (var modelProperty in catelProperties) { var propertyData = modelProperty.Value; if (!propertyData.IsSerializable) { Log.Warning("Property '{0}' is not serializable, so will be excluded from the serialization", propertyData.Name); continue; } if (!propertyData.IncludeInSerialization) { Log.Debug("Property '{0}' is flagged to be excluded from serialization", propertyData.Name); continue; } var propertyType = type.GetPropertyEx(modelProperty.Value.Name); if (propertyType != null) { if (!AttributeHelper.IsDecoratedWithAttribute<ExcludeFromSerializationAttribute>(propertyType)) { properties.Add(modelProperty.Key); } } else { // Dynamic property, always include properties.Add(modelProperty.Key); } } var typeProperties = type.GetPropertiesEx(); foreach (var typeProperty in typeProperties) { if (!catelPropertyNames.Contains(typeProperty.Name)) { if (AttributeHelper.IsDecoratedWithAttribute<IncludeInSerializationAttribute>(typeProperty)) { properties.Add(typeProperty.Name); } } } return new HashSet<string>(properties); }); }
/// <summary> /// Initializes the view model meta data. /// <para /> /// This method only initializes the meta data once per view model type. If a type is already initialized, /// this method will immediately return. /// </summary> /// <param name="viewModelType">Type of the view model.</param> /// <returns>ViewModelMetadata.</returns> /// <exception cref="ArgumentNullException">The <paramref name="viewModelType" /> is <c>null</c>.</exception> private static ViewModelMetadata InitializeViewModelMetaData(Type viewModelType) { if (_metaData.ContainsKey(viewModelType)) { return _metaData[viewModelType]; } var properties = new List<PropertyInfo>(); var bindingFlags = BindingFlagsHelper.GetFinalBindingFlags(true, false, true); properties.AddRange(viewModelType.GetPropertiesEx(bindingFlags)); var modelObjectsInfo = new Dictionary<string, ModelInfo>(); var viewModelToModelMap = new Dictionary<string, ViewModelToModelMapping>(); var validationSummaries = new Dictionary<string, ValidationToViewModelAttribute>(); foreach (var propertyInfo in properties) { #region Model attributes var modelAttribute = propertyInfo.GetCustomAttributeEx(typeof(ModelAttribute), true) as ModelAttribute; if (modelAttribute != null) { modelObjectsInfo.Add(propertyInfo.Name, new ModelInfo(propertyInfo.Name, modelAttribute)); } #endregion #region ViewModelToModel attributes var viewModelToModelAttribute = propertyInfo.GetCustomAttributeEx(typeof(ViewModelToModelAttribute), true) as ViewModelToModelAttribute; if (viewModelToModelAttribute != null) { if (string.IsNullOrEmpty(viewModelToModelAttribute.Property)) { // Assume the property name in the model is the same as in the view model viewModelToModelAttribute.Property = propertyInfo.Name; } if (!viewModelToModelMap.ContainsKey(propertyInfo.Name)) { viewModelToModelMap.Add(propertyInfo.Name, new ViewModelToModelMapping(propertyInfo.Name, viewModelToModelAttribute)); } } #endregion #region ValidationToViewModel attributes var validationToViewModelAttribute = propertyInfo.GetCustomAttributeEx(typeof(ValidationToViewModelAttribute), true) as ValidationToViewModelAttribute; if (validationToViewModelAttribute != null) { if (propertyInfo.PropertyType != typeof(IValidationSummary)) { throw Log.ErrorAndCreateException<InvalidOperationException>("A property decorated with the ValidationToViewModel attribute must be of type IValidationSummary, but '{0}' is not", propertyInfo.Name); } validationSummaries.Add(propertyInfo.Name, validationToViewModelAttribute); Log.Debug("Registered property '{0}' as validation summary", propertyInfo.Name); } #endregion } _metaData.Add(viewModelType, new ViewModelMetadata(viewModelType, modelObjectsInfo, viewModelToModelMap, validationSummaries)); return _metaData[viewModelType]; }
/// <summary> /// Gets the regular properties. /// </summary> /// <param name="type">Type of the model.</param> /// <returns>A hash set containing the regular properties.</returns> /// <exception cref="ArgumentNullException">The <paramref name="type"/> is <c>null</c>.</exception> public Dictionary<string, MemberMetadata> GetRegularProperties(Type type) { Argument.IsNotNull("type", type); return _regularPropertiesCache.GetFromCacheOrFetch(type, () => { var dictionary = new Dictionary<string, MemberMetadata>(); var catelPropertyNames = GetCatelPropertyNames(type, true); var regularProperties = type.GetPropertiesEx(); foreach (var propertyInfo in regularProperties) { if (catelPropertyNames.Contains(propertyInfo.Name) || propertyInfo.DeclaringType == typeof(ModelBase)) { continue; } var memberMetadata = new MemberMetadata(type, propertyInfo.PropertyType, SerializationMemberGroup.RegularProperty, propertyInfo.Name) { Tag = propertyInfo }; var nameOverride = GetNameOverrideForSerialization(propertyInfo); if (!string.IsNullOrWhiteSpace(nameOverride)) { memberMetadata.MemberNameForSerialization = nameOverride; } dictionary[propertyInfo.Name] = memberMetadata; } return dictionary; }); }
/// <summary> /// Initializes a new instance of the <see cref="ViewModelCommandManager" /> class. /// </summary> /// <param name="viewModel">The view model.</param> /// <exception cref="ArgumentNullException">The <paramref name="viewModel"/> is <c>null</c>.</exception> private ViewModelCommandManager(IViewModel viewModel) { Argument.IsNotNull("viewModel", viewModel); Log.Debug("Creating a ViewModelCommandManager for view model '{0}' with unique identifier '{1}'", viewModel.GetType().FullName, viewModel.UniqueIdentifier); _viewModel = viewModel; _viewModelType = viewModel.GetType(); _viewModel.Initialized += OnViewModelInitialized; _viewModel.PropertyChanged += OnViewModelPropertyChanged; _viewModel.Closed += OnViewModelClosed; var properties = new List<PropertyInfo>(); properties.AddRange(_viewModelType.GetPropertiesEx()); foreach (var propertyInfo in properties) { if (propertyInfo.PropertyType.ImplementsInterfaceEx(typeof(ICommand))) { _commandProperties.Add(propertyInfo); } } RegisterCommands(false); Log.Debug("Created a ViewModelCommandManager for view model '{0}' with unique identifier '{1}'", viewModel.GetType().FullName, viewModel.UniqueIdentifier); }
private static MemberInfo TryFindMetaMemberInfo(Type metaType, MemberInfo member) { var flags = MemberFlags.Public | MemberFlags.NonPublic | MemberFlags.Instance; var property = member as PropertyInfo; if (property != null) return metaType .GetPropertiesEx(flags) .FirstOrDefault( info => info.Name == property.Name && info.GetIndexParameters().SequenceEqual(property.GetIndexParameters())); var field = member as FieldInfo; if (field != null) return metaType.GetFieldEx(field.Name, flags); var method = member as MethodInfo; if (method != null) return metaType .GetMethodsEx(flags) .FirstOrDefault(info => info.Name == method.Name && info.ReturnType.Equals(method.ReturnType) && info.GetParameters() .Select(parameterInfo => parameterInfo.ParameterType) .SequenceEqual(method.GetParameters().Select(parameterInfo => parameterInfo.ParameterType))); var eventInfo = member as EventInfo; if (eventInfo != null) #if PCL_WINRT return metaType.GetRuntimeEvents().FirstOrDefault(info => info.Name == eventInfo.Name); #else return metaType.GetEvents().FirstOrDefault(info => info.Name == eventInfo.Name); #endif return null; }