/// <summary> /// Gets the fields from an enum. /// </summary> /// <param name="enumType">Type of the enum.</param> /// <returns>Array of <see cref="FieldInfo"/> values.</returns> private static FieldInfo[] GetFields(Type enumType) { var fields = enumType.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, true)); fields = (from field in fields where field.IsLiteral && field.IsPublic select field).ToArray(); return(fields.ToArray()); }
/// <summary> /// Finds the fields that represent a <see cref="PropertyData"/>. /// </summary> /// <param name="type">The type.</param> /// <returns>The list of <see cref="PropertyData"/> elements found as fields.</returns> /// <exception cref="InvalidOperationException">One ore more fields are not declared correctly.</exception> private IEnumerable <PropertyData> FindCatelFields(Type type) { // CTL-212: Generic types are not supported for FieldInfo.GetValue if (type.ContainsGenericParametersEx()) { return(new PropertyData[] { }); } // Fields - safety checks for non-static fields var nonStaticFields = (from field in type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, false, true)) where field.FieldType == typeof(PropertyData) select field).ToList(); foreach (var nonStaticField in nonStaticFields) { string error = string.Format("The field '{0}' of type 'PropertyData' declared as instance, but they can only be used as static", nonStaticField.Name); Log.Error(error); throw new InvalidOperationException(error); } // Fields - safety checks for non-public fields var nonPublicFields = (from field in type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, true, true)) where field.FieldType == typeof(PropertyData) && !field.IsPublic select field).ToList(); foreach (var nonPublicField in nonPublicFields) { string error = string.Format("The field '{0}' of type 'PropertyData' declared as non-public, but they can only be used as public", nonPublicField.Name); Log.Error(error); throw new InvalidOperationException(error); } // Fields - actual addition var foundFields = new List <PropertyData>(); var fields = new List <FieldInfo>(); fields.AddRange(type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, true, false))); foreach (var field in fields) { if (field.FieldType == typeof(PropertyData)) { var propertyValue = (field.IsStatic ? field.GetValue(null) : field.GetValue(this)) as PropertyData; if (propertyValue != null) { foundFields.Add(propertyValue); } } } return(foundFields); }
/// <summary> /// The get events ex. /// </summary> /// <param name="type">The type.</param> /// <param name="flattenHierarchy">The flatten Hierarchy.</param> /// <param name="allowStaticMembers">The allow Static Members.</param> /// <returns>EventInfo[][].</returns> /// <exception cref="System.ArgumentNullException">The <paramref name="type" /> is <c>null</c>.</exception> public static EventInfo[] GetEventsEx(this Type type, bool flattenHierarchy = true, bool allowStaticMembers = false) { Argument.IsNotNull(nameof(type), type); var bindingFlags = BindingFlagsHelper.GetFinalBindingFlags(flattenHierarchy, allowStaticMembers); #if ENABLE_CACHE var cacheKey = new ReflectionCacheKey(type, ReflectionTypes.Event, bindingFlags); return(_eventsCache.GetFromCacheOrFetch(cacheKey, () => type.GetTypeInfo().GetEvents(bindingFlags))); #else return(type.GetTypeInfo().GetEvents(bindingFlags)); #endif }
private void PreventWrongDeclaredFields(Type type) { // Fields - safety checks for non-static fields var nonStaticFields = (from field in type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, false, true)) where field.FieldType == typeof(PropertyData) select field).ToList(); if (nonStaticFields.Count > 0) { var nonStaticField = nonStaticFields[0]; throw Log.ErrorAndCreateException <InvalidOperationException>("The field '{0}' of type 'PropertyData' declared as instance, but they can only be used as static", nonStaticField.Name); } }
private void PreventWrongDeclaredProperties(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(); if (nonStaticProperties.Count > 0) { var nonStaticProperty = nonStaticProperties[0]; throw Log.ErrorAndCreateException <InvalidOperationException>("The property '{0}' of type 'PropertyData' declared as instance, but they can only be used as static", nonStaticProperty.Name); } }
/// <summary> /// Subscribes all methods of the specified instance that are decorated with the <see cref="MessageRecipientAttribute"/>. /// </summary> /// <param name="instance">The instance to subscribe.</param> /// <param name="messageMediator">The message mediator. If <c>null</c>, the default will be used.</param> /// <exception cref="ArgumentNullException">The <paramref name="instance"/> is <c>null</c>.</exception> /// <exception cref="NotSupportedException">The object has non-public methods decorated with the <see cref="MessageRecipientAttribute"/>, but the /// application is not written in .NET (but in SL, WP7 or WinRT).</exception> /// <exception cref="InvalidCastException">One of the methods cannot be casted to a valid message method.</exception> public static void SubscribeRecipient(object instance, IMessageMediator messageMediator = null) { Argument.IsNotNull("instance", instance); if (messageMediator == null) { var dependencyResolver = IoCConfiguration.DefaultDependencyResolver; messageMediator = dependencyResolver.Resolve <IMessageMediator>(); } var mediator = messageMediator; var methodInfos = instance.GetType().GetMethodsEx(BindingFlagsHelper.GetFinalBindingFlags(true, false)); foreach (var methodInfo in methodInfos) { var customAttributes = methodInfo.GetCustomAttributesEx(typeof(MessageRecipientAttribute), true); foreach (var customAttribute in customAttributes) { var attribute = (MessageRecipientAttribute)customAttribute; var parameterInfos = methodInfo.GetParameters(); Type actionType; Type actionParameterType; switch (parameterInfos.Length) { case 0: actionType = typeof(Action <object>); actionParameterType = typeof(object); break; case 1: actionType = typeof(Action <>).MakeGenericType(parameterInfos[0].ParameterType); actionParameterType = parameterInfos[0].ParameterType; break; default: var error = string.Format("Cannot cast '{0}' to Action or Action<T> delegate type.", methodInfo.Name); Log.Error(error); throw new InvalidCastException(error); } var tag = attribute.Tag; var action = DelegateHelper.CreateDelegate(actionType, instance, methodInfo); var registerMethod = mediator.GetType().GetMethodEx("Register").MakeGenericMethod(actionParameterType); registerMethod.Invoke(mediator, new[] { instance, action, tag }); } } }
/// <summary> /// Initializes the default values. /// </summary> /// <param name="obj">The obj.</param> /// <exception cref="ArgumentNullException">The <paramref name="obj"/> is <c>null</c>.</exception> private void InitializeDefaultValues(object obj) { Argument.IsNotNull("obj", obj); var properties = obj.GetType().GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(true, false)); foreach (var property in properties) { if (!ShouldPropertyBeIgnored(obj, property.Name)) { _previousPropertyValues[property.Name] = PropertyHelper.GetPropertyValue(obj, property.Name); } } }
/// <summary> /// Gets the exports from key. /// </summary> /// <param name="container">The container.</param> /// <param name="key">The key.</param> /// <returns> /// An enumeration of exports. /// </returns> /// <exception cref="ArgumentNullException">The <paramref name="container"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">The <paramref name="key"/> is <c>null</c>.</exception> private IEnumerable <object> GetExportsFromKey(object container, string key) { Argument.IsNotNull("container", container); Argument.IsNotNull("key", key); // Retrieve GetExports<T>(string contractName) var methods = container.GetType().GetMethodsEx(BindingFlagsHelper.GetFinalBindingFlags(false, true)); var getExportsMethodInfo = methods.Where(method => method.Name == "GetExports"). Where(method => method.GetGenericArguments().Count() == 1). Where(method => method.GetParameters().Count() == 1).FirstOrDefault(); var genericMethodInfo = getExportsMethodInfo.MakeGenericMethod(new[] { typeof(object) }); return(((IEnumerable)genericMethodInfo.Invoke(container, new object[] { key })).Cast <object>()); }
/// <summary> /// Initializes a new instance of the <see cref="EventTarget"/> class. /// </summary> /// <param name="associatedObject">The associated object.</param> /// <param name="eventTarget">The event target as string representation.</param> /// <remarks> /// If the parsing fails, no exception will be thrown but the <see cref="ControlName"/> /// and <see cref="EventName"/> will remain empty. /// </remarks> /// <exception cref="ArgumentNullException">The <paramref name="associatedObject"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">The <paramref name="eventTarget"/> is <c>null</c> or whitespace.</exception> /// <exception cref="InvalidOperationException">The <paramref name="associatedObject"/> is not yet loaded.</exception> public EventTarget(FrameworkElement associatedObject, string eventTarget) { Argument.IsNotNull("associatedObject", associatedObject); Argument.IsNotNullOrWhitespace("eventTarget", eventTarget); #if NET if (!associatedObject.IsLoaded) { throw new InvalidOperationException("The associated object is not yet loaded, which is required"); } #endif _associatedObject = associatedObject; ControlName = string.Empty; EventName = string.Empty; int dotIndex = eventTarget.IndexOf('.'); if (dotIndex == -1) { ControlName = eventTarget; EventName = "Click"; } else { ControlName = eventTarget.Substring(0, dotIndex); EventName = eventTarget.Substring(dotIndex + 1, eventTarget.Length - dotIndex - 1); } _target = _associatedObject.FindName(ControlName); if (_target == null) { throw new InvalidOperationException(string.Format("'{0}' resulted in control name '{1}', which cannot be found on the associated object", eventTarget, ControlName)); } _eventInfo = _target.GetType().GetEventEx(EventName); if (_eventInfo == null) { throw new InvalidOperationException(string.Format("'{0}' resulted in event name '{1}', which cannot be found on target '{2}'", eventTarget, EventName, ControlName)); } var methodInfo = GetType().GetMethodEx("OnEvent", BindingFlagsHelper.GetFinalBindingFlags(true, false)); var boundEventHandler = methodInfo.MakeGenericMethod(new[] { _eventInfo.EventHandlerType.GetMethodEx("Invoke").GetParameters()[1].ParameterType }); _delegate = DelegateHelper.CreateDelegate(_eventInfo.EventHandlerType, this, boundEventHandler); _eventInfo.AddEventHandler(_target, _delegate); }
/// <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> /// Initializes the XML property mappings. /// </summary> /// <param name="type">The type for which to initialize the xml mappings.</param> private void InitializeXmlPropertyMappings(Type type) { if (_xmlNameToPropertyNameMappings.ContainsKey(type)) { return; } lock (_xmlMappingsLock) { _xmlNameToPropertyNameMappings.Add(type, new Dictionary <string, string>()); _xmlPropertyNameToXmlNameMappings.Add(type, new Dictionary <string, string>()); var catelTypeInfo = _propertyDataManager.GetCatelTypeInfo(type); foreach (var propertyData in catelTypeInfo.GetCatelProperties()) { var propertyInfo = type.GetPropertyEx(propertyData.Key, BindingFlagsHelper.GetFinalBindingFlags(true, false)); if (propertyInfo == null) { // Dynamic property, not mapped (always fixed) continue; } // 1st, check if XmlIgnore is used if (AttributeHelper.IsDecoratedWithAttribute <XmlIgnoreAttribute>(propertyInfo)) { continue; } // 2nd, check if XmlAttribute is used XmlAttributeAttribute xmlAttributeAttribute = null; AttributeHelper.TryGetAttribute(propertyInfo, out xmlAttributeAttribute); if (InitializeXmlAttributeAttribute(type, xmlAttributeAttribute, propertyData.Key)) { continue; } // 3rd, check if XmlElement is used XmlElementAttribute xmlElementAttribute = null; AttributeHelper.TryGetAttribute(propertyInfo, out xmlElementAttribute); if (InitializeXmlElementAttribute(type, xmlElementAttribute, propertyData.Key)) { continue; } } } }
/// <summary> /// Creates the dynamic closed delegate. /// </summary> /// <param name="eventHandlerType">Type of the event handler.</param> /// <returns>A dynamically created closed delegate.</returns> private Delegate CreateDynamicHandlerDelegate(Type eventHandlerType) { var handler = new DynamicMethod("DynamicEventHandler", null, GetDelegateParameterTypes(eventHandlerType)); ILGenerator ilgen = handler.GetILGenerator(); var handlerMethodInfo = GetType().GetMethodEx("OnEvent", BindingFlagsHelper.GetFinalBindingFlags(false, false)); // this.OnTargetWindowClosed ilgen.Emit(OpCodes.Ldsfld, typeof(DynamicEventListener).GetFieldEx("Instances", BindingFlagsHelper.GetFinalBindingFlags(false, true))); ilgen.Emit(OpCodes.Ldc_I4, UniqueIdentifier); ilgen.Emit(OpCodes.Call, typeof(HandlerDictionary).GetMethodEx("Get", BindingFlagsHelper.GetFinalBindingFlags(true, false))); ilgen.Emit(OpCodes.Call, handlerMethodInfo); ilgen.Emit(OpCodes.Ret); return(handler.CreateDelegate(eventHandlerType)); }
/// <summary> /// Ensures that the dependency properties of the specified <see cref="FrameworkElement"/> are in the cache. /// </summary> /// <param name="frameworkElement">The framework element.</param> /// <exception cref="ArgumentNullException">The <paramref name="frameworkElement"/> is <c>null</c>.</exception> private static void EnsureItemInCache(this FrameworkElement frameworkElement) { Argument.IsNotNull("frameworkElement", frameworkElement); var type = frameworkElement.GetType(); if (_cacheByParentType.ContainsKey(type)) { return; } var properties = new List <DependencyPropertyInfo>(); var parentType = type; var fields = parentType.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, true)); foreach (var field in fields) { if (typeof(DependencyProperty).IsAssignableFromEx(field.FieldType)) { var names = field.ToString().Split(new[] { ' ' }); var name = names[names.Length - 1]; int propertyPostfixIndex = name.LastIndexOf("Property"); if (propertyPostfixIndex != -1) { name = name.Substring(0, propertyPostfixIndex); } if (string.Equals(name, "__Direct") || string.Equals(name, "DirectDependency")) { continue; } var dependencyProperty = (DependencyProperty)field.GetValue(frameworkElement); properties.Add(new DependencyPropertyInfo(dependencyProperty, name)); var propertyKey = GetDependencyPropertyCacheKey(frameworkElement, name); _cacheByPropertyName[propertyKey] = dependencyProperty; _cacheByDependencyProperty[dependencyProperty] = name; } } _cacheByParentType[type] = properties; }
/// <summary> /// Modifies the source data before passing it to the target for display in the UI. /// </summary> /// <param name="value">The source data being passed to the target.</param> /// <param name="targetType">The <see cref="T:System.Type" /> of data expected by the target dependency property.</param> /// <param name="parameter">An optional parameter to be used in the converter logic.</param> /// <returns>The value to be passed to the target dependency property.</returns> protected override object Convert(object value, Type targetType, object parameter) { var methodName = parameter as string; if (value == null || methodName == null) { return(value); } var methodInfo = value.GetType().GetMethodEx(methodName, new Type[0], BindingFlagsHelper.GetFinalBindingFlags(true, true)); if (methodInfo == null) { return(value); } return(methodInfo.Invoke(value, new object[0])); }
/// <summary> /// Modifies the source data before passing it to the target for display in the UI. /// </summary> /// <param name="value">The source data being passed to the target.</param> /// <param name="targetType">The <see cref="T:System.Type" /> of data expected by the target dependency property.</param> /// <param name="parameter">An optional parameter to be used in the converter logic.</param> /// <returns>The value to be passed to the target dependency property.</returns> protected override object Convert(object value, Type targetType, object parameter) { var methodName = parameter as string; if (value is null || methodName is null) { return(value); } var bindingFlags = BindingFlagsHelper.GetFinalBindingFlags(true, true); var methodInfo = value.GetType().GetMethodEx(methodName, ArrayShim.Empty <Type>(), bindingFlags); if (methodInfo is null) { return(value); } return(methodInfo.Invoke(value, ArrayShim.Empty <object>())); }
/// <summary> /// The get constructor ex. /// </summary> /// <param name="type">The type.</param> /// <param name="types">The types.</param> /// <returns>ConstructorInfo.</returns> /// <exception cref="System.ArgumentNullException">The <paramref name="type" /> is <c>null</c>.</exception> /// <exception cref="System.ArgumentNullException">The <paramref name="types" /> is <c>null</c>.</exception> public static ConstructorInfo GetConstructorEx(this Type type, Type[] types) { Argument.IsNotNull(nameof(type), type); Argument.IsNotNull(nameof(types), types); #if ENABLE_CACHE var cacheKey = new ReflectionCacheKey(type, ReflectionTypes.Constructor, BindingFlags.Default, types); #if NETFX_CORE || PCL return(_constructorCache.GetFromCacheOrFetch(cacheKey, () => type.GetTypeInfo().GetConstructor(types, BindingFlagsHelper.GetFinalBindingFlags(false, false)))); #else return(_constructorCache.GetFromCacheOrFetch(cacheKey, () => type.GetConstructor(types))); #endif #else #if NETFX_CORE || PCL return(type.GetTypeInfo().GetConstructor(types, BindingFlagsHelper.GetFinalBindingFlags(false, false))); #else return(type.GetConstructor(types)); #endif #endif }
/// <summary> /// Subscribes to the event. /// </summary> private void SubscribeToEvent() { if (_isSubscribed) { return; } lock (Instances) { Instances.Add(UniqueIdentifier, this); } _eventInfo = _eventInstanceType.GetEventEx(EventName, BindingFlagsHelper.GetFinalBindingFlags(true, false)); if (_eventInfo == null) { throw Log.ErrorAndCreateException <NotSupportedException>("Cannot find the '{0}' event, implement the '{0}' event on '{1}'", EventName, _eventInstanceType.Name); } _handler = CreateDynamicHandlerDelegate(_eventInfo.EventHandlerType); _eventInfo.AddEventHandler(_eventInstance, _handler); }
/// <summary> /// Registers a specific instance for the specified interface. /// </summary> /// <param name="container">The container.</param> /// <param name="interfaceType">Type of the interface.</param> /// <param name="implementingInstance">The implementing instance.</param> /// <exception cref="ArgumentNullException">If <paramref name="container"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="interfaceType"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="implementingInstance"/> is <c>null</c>.</exception> /// <exception cref="NotSupportedException">If <paramref name="container"/> is not a MEF IoC container.</exception> public override void RegisterInstance(object container, Type interfaceType, object implementingInstance) { Argument.IsNotNull("container", container); Argument.IsNotNull("interfaceType", interfaceType); Argument.IsNotNull("implementingInstance", implementingInstance); if (!IsValidContainer(container)) { throw new NotSupportedException("Only MEF containers are supported"); } var attributedModelServicesType = GetContainerType("System.ComponentModel.Composition.AttributedModelServices", container); // Retrieve ComposeExportedValue<T>(this CompositionContainer container, T exportedValue) var methods = attributedModelServicesType.GetMethodsEx(BindingFlagsHelper.GetFinalBindingFlags(false, true)); var composeExportedValueMethodInfo = methods.Where(method => method.Name == "ComposeExportedValue"). Where(method => method.GetGenericArguments().Count() == 1). Where(method => method.GetParameters().Count() == 2).FirstOrDefault(); var genericComposeExportedValue = composeExportedValueMethodInfo.MakeGenericMethod(new[] { interfaceType }); genericComposeExportedValue.Invoke(null, new[] { container, implementingInstance }); }
/// <summary> /// Gets the dependency property with the specified property name. /// </summary> /// <param name="dependencyPropertyName">Name of the property.</param> /// <returns>The <see cref="DependencyProperty"/> or <c>null</c> if the dependency property is not found.</returns> private DependencyProperty GetDependencyProperty(string dependencyPropertyName) { DependencyProperty property = null; var bindingFlags = BindingFlagsHelper.GetFinalBindingFlags(true, true); var fieldInfo = AssociatedObject.GetType().GetFieldEx(dependencyPropertyName, bindingFlags); if (fieldInfo != null) { property = fieldInfo.GetValue(null) as DependencyProperty; } if (property == null) { Log.Error("Failed to retrieve dependency property '{0}' from object '{1}'", dependencyPropertyName, AssociatedObject.GetType()); } else { Log.Debug("Retrieved dependency property '{0}' from object '{1}'", dependencyPropertyName, AssociatedObject.GetType()); } return(property); }
/// <summary> /// Ensures that the dependency properties of the specified <see cref="FrameworkElement"/> are in the cache. /// </summary> /// <param name="viewType">The view type.</param> /// <exception cref="ArgumentNullException">The <paramref name="viewType"/> is <c>null</c>.</exception> private static void EnsureItemInCache(this Type viewType) { if (_cacheByParentType.ContainsKey(viewType)) { return; } var properties = new List <DependencyPropertyInfo>(); var bindingFlags = BindingFlagsHelper.GetFinalBindingFlags(true, true); var typeMembers = new List <MemberInfo>(); typeMembers.AddRange(viewType.GetFieldsEx(bindingFlags)); typeMembers.AddRange(viewType.GetPropertiesEx(bindingFlags)); foreach (var member in typeMembers) { try { var fieldInfo = member as FieldInfo; var propertyInfo = member as PropertyInfo; if (fieldInfo != null) { if (!typeof(DependencyProperty).IsAssignableFromEx(fieldInfo.FieldType)) { continue; } } else if (propertyInfo != null) { if (!typeof(DependencyProperty).IsAssignableFromEx(propertyInfo.PropertyType)) { continue; } } string name = member.Name; int propertyPostfixIndex = name.LastIndexOf("Property", StringComparison.Ordinal); if (propertyPostfixIndex != -1) { name = name.Substring(0, propertyPostfixIndex); } if (string.Equals(name, "__Direct") || string.Equals(name, "DirectDependency")) { continue; } DependencyProperty dependencyProperty; if (fieldInfo != null) { var fieldValue = fieldInfo.GetValue(null); dependencyProperty = fieldValue as DependencyProperty; } else if (propertyInfo != null) { #if NETFX_CORE var propertyValue = propertyInfo.GetValue(null); dependencyProperty = propertyValue as DependencyProperty; #else var propertyValue = propertyInfo.GetValue(null, null); dependencyProperty = propertyValue as DependencyProperty; #endif } else { continue; } if (dependencyProperty == null) { continue; } properties.Add(new DependencyPropertyInfo(dependencyProperty, name)); string propertyKey = GetDependencyPropertyCacheKey(viewType, name); _cacheByPropertyName[propertyKey] = dependencyProperty; _cacheByDependencyProperty[dependencyProperty] = name; } catch (Exception ex) { Log.Warning(ex, $"Failed to enumerate member '{member.Name}' as dependency property"); } } _cacheByParentType[viewType] = properties; }
/// <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()); }
/// <summary> /// Ensures that the dependency properties of the specified <see cref="FrameworkElement"/> are in the cache. /// </summary> /// <param name="frameworkElement">The framework element.</param> /// <exception cref="ArgumentNullException">The <paramref name="frameworkElement"/> is <c>null</c>.</exception> private static void EnsureItemInCache(this FrameworkElement frameworkElement) { Argument.IsNotNull("frameworkElement", frameworkElement); var type = frameworkElement.GetType(); if (_cacheByParentType.ContainsKey(type)) { return; } var properties = new List <DependencyPropertyInfo>(); var typeMembers = new List <MemberInfo>(); typeMembers.AddRange(type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, true))); typeMembers.AddRange(type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(true, true))); foreach (MemberInfo member in typeMembers) { var fieldInfo = member as FieldInfo; var propertyInfo = member as PropertyInfo; if (fieldInfo != null) { if (!typeof(DependencyProperty).IsAssignableFromEx(fieldInfo.FieldType)) { continue; } } else if (propertyInfo != null) { if (!typeof(DependencyProperty).IsAssignableFromEx(propertyInfo.PropertyType)) { continue; } } string name = member.Name; int propertyPostfixIndex = name.LastIndexOf("Property", StringComparison.Ordinal); if (propertyPostfixIndex != -1) { name = name.Substring(0, propertyPostfixIndex); } if (string.Equals(name, "__Direct") || string.Equals(name, "DirectDependency")) { continue; } DependencyProperty dependencyProperty; if (fieldInfo != null) { dependencyProperty = (DependencyProperty)fieldInfo.GetValue(frameworkElement); } else if (propertyInfo != null) { #if NETFX_CORE dependencyProperty = (DependencyProperty)propertyInfo.GetValue(frameworkElement); #else dependencyProperty = (DependencyProperty)propertyInfo.GetValue(frameworkElement, null); #endif } else { continue; } properties.Add(new DependencyPropertyInfo(dependencyProperty, name)); string propertyKey = GetDependencyPropertyCacheKey(frameworkElement, name); _cacheByPropertyName[propertyKey] = dependencyProperty; _cacheByDependencyProperty[dependencyProperty] = name; } _cacheByParentType[type] = properties; }
/// <summary> /// Called when the event occurs. /// </summary> // ReSharper disable UnusedMember.Global public void OnEvent() // ReSharper restore UnusedMember.Global { EventOccurred.SafeInvoke(this); if (_handlerInstance != null) { var handlerMethodInfo = _handlerInstance.GetType().GetMethodEx(HandlerName, BindingFlagsHelper.GetFinalBindingFlags(true, false)); if (handlerMethodInfo == null) { throw Log.ErrorAndCreateException <NotSupportedException>("Cannot find the '{0}' method, implement the '{0}' method on '{1}'", EventName, _handlerInstance.GetType().Name); } handlerMethodInfo.Invoke(_handlerInstance, null); } }
/// <summary> /// Gets the <see cref="PropertyInfo"/> for the specified property. /// </summary> /// <param name="property">The name of the property.</param> /// <returns><see cref="PropertyInfo"/> or <c>null</c> if no property info is found.</returns> protected PropertyInfo GetPropertyInfo(string property) { return(GetType().GetPropertyEx(property, BindingFlagsHelper.GetFinalBindingFlags(true, false))); }
public void ReturnsInstanceMethods() { var methods = typeof(DerivedClass).GetMethodsEx(BindingFlagsHelper.GetFinalBindingFlags(true, false, true), true); Assert.IsTrue(methods.Any(x => x.Name == "Method2")); }
public void ReturnsInstanceProperties() { var properties = typeof(DerivedClass).GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(true, false, true), true); Assert.IsTrue(properties.Any(x => x.Name == "Property2")); }
public void ReturnsStaticFields() { var fields = typeof(DerivedClass).GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(true, true, true), true); Assert.IsTrue(fields.Any(x => x.Name == "field1")); }
/// <summary> /// Gets the known types inside the specific type. /// </summary> /// <param name="type">The type to retrieve the known types for.</param> /// <param name="knownTypeList">The known type list.</param> /// <param name="alreadyCheckedTypes">The already checked types.</param> /// <returns> /// Array of <see cref="Type"/> that are found in the object type. /// </returns> /// <exception cref="ArgumentNullException">The <paramref name="knownTypeList"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">The <paramref name="alreadyCheckedTypes"/> is <c>null</c>.</exception> private static Type[] GetKnownTypes(Type type, HashSet <Type> knownTypeList, HashSet <Type> alreadyCheckedTypes) { if (!ShouldTypeBeHandled(type, knownTypeList, alreadyCheckedTypes)) { return(knownTypeList.ToArray()); } Log.Debug("Getting known types for '{0}'", type.FullName); // If this is an interface, HOUSTON, WE HAVE A PROBLEM if (type.IsInterfaceEx()) { if (!alreadyCheckedTypes.Contains(type)) { Log.Debug("Type is an interface, checking all types deriving from this interface"); // Don't check this interface again in children checks alreadyCheckedTypes.Add(type); // Interfaces are not a type, and in fact a LOT of types can be added (in fact every object implementing the interface). For // serialization, this is not a problem (we know the exact type), but for deserialization this IS an issue because we should // expect EVERY type that implements the type in the whole AppDomain. // // This is huge performance hit, but it's the cost for dynamic easy on-the-fly serialization in WPF and Silverlight. Luckily // we already implemented caching. var typesDerivingFromInterface = TypeCache.GetTypes(t => t.IsAssignableFromEx(type)); foreach (var typeDerivingFromInterface in typesDerivingFromInterface) { if (typeDerivingFromInterface != type) { GetKnownTypes(typeDerivingFromInterface, knownTypeList, alreadyCheckedTypes); } } Log.Debug("Finished checking all types deriving from this interface"); } // The interface itself is ignored return(knownTypeList.ToArray()); } if (IsSpecialCollectionType(type) && !type.IsInterfaceEx()) { Log.Debug("Type is a special collection type, adding it to the array of known types"); AddTypeToKnownTypesIfSerializable(knownTypeList, type); } // Fix generics if (type.FullName.StartsWith("System.")) { Type[] genericArguments = type.GetTypeInfo().GenericTypeArguments; foreach (var genericArgument in genericArguments) { Log.Debug("Retrieving known types for generic argument '{0}' of '{1}'", genericArgument.FullName, type.FullName); GetKnownTypes(genericArgument, knownTypeList, alreadyCheckedTypes); } return(knownTypeList.ToArray()); } if (!AddTypeToKnownTypesIfSerializable(knownTypeList, type)) { alreadyCheckedTypes.Add(type); } // Fields var fields = type.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false)); foreach (var field in fields) { Log.Debug("Getting known types for field '{0}' of '{1}'", field.Name, type.FullName); var fieldType = field.FieldType; if (fieldType.FullName != null) { GetKnownTypes(fieldType, knownTypeList, alreadyCheckedTypes); } else { alreadyCheckedTypes.Add(fieldType); } } // Properties var properties = type.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false)); foreach (var property in properties) { Log.Debug("Getting known types for property '{0}' of '{1}'", property.Name, type.FullName); var propertyType = property.PropertyType; if (propertyType.FullName != null) { GetKnownTypes(propertyType, knownTypeList, alreadyCheckedTypes); } else { alreadyCheckedTypes.Add(propertyType); } } // If this isn't the base type, check that as well var baseType = type.GetTypeInfo().BaseType; if (baseType != null) { Log.Debug("Checking base type of '{0}' for known types", type.FullName); if (baseType.FullName != null) { GetKnownTypes(baseType, knownTypeList, alreadyCheckedTypes); } else { alreadyCheckedTypes.Add(baseType); } } // Last but not least, check if the type is decorated with KnownTypeAttributes var knowTypesByAttributes = GetKnownTypesViaAttributes(type); if (knowTypesByAttributes.Length > 0) { Log.Debug("Found {0} additional known types for type '{1}'", knowTypesByAttributes.Length, type.FullName); foreach (var knownTypeByAttribute in knowTypesByAttributes) { var attributeType = knownTypeByAttribute; if (attributeType.FullName != null) { GetKnownTypes(knownTypeByAttribute, knownTypeList, alreadyCheckedTypes); } else { alreadyCheckedTypes.Add(attributeType); } } } return(knownTypeList.ToArray()); }
/// <summary> /// Gets the known types for a specific object instance. /// </summary> /// <param name="obj">The object to retrieve the known types for.</param> /// <param name="knownTypeList">The known type list.</param> /// <param name="alreadyCheckedTypes">The already checked types.</param> /// <returns> /// Array of <see cref="Type"/> that are found in the object instance. /// </returns> /// <exception cref="ArgumentNullException">The <paramref name="knownTypeList"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">The <paramref name="alreadyCheckedTypes"/> is <c>null</c>.</exception> private static Type[] GetKnownTypesForInstance(object obj, HashSet <Type> knownTypeList, HashSet <Type> alreadyCheckedTypes) { Argument.IsNotNull("knownTypeList", knownTypeList); Argument.IsNotNull("alreadyCheckedTypes", alreadyCheckedTypes); if (obj == null) { return(knownTypeList.ToArray()); } Type objectType = obj.GetType(); if (!ShouldTypeBeHandled(objectType, knownTypeList, alreadyCheckedTypes)) { return(knownTypeList.ToArray()); } Log.Debug("Getting known types for instance of '{0}'", objectType.FullName); GetKnownTypes(objectType, knownTypeList, alreadyCheckedTypes); if (objectType.FullName == null) { alreadyCheckedTypes.Add(objectType); return(knownTypeList.ToArray()); } // Collections might contain interface types, so if this is an IEnumerable, we need to loop all the instances (performance warning!) var objAsIEnumerable = obj as IEnumerable; if ((objAsIEnumerable != null) && (!(obj is string))) { foreach (object item in objAsIEnumerable) { if (item != null) { GetKnownTypesForInstance(item, knownTypeList, alreadyCheckedTypes); } } } if (objectType == typeof(List <KeyValuePair <string, object> >)) { foreach (var keyValuePair in ((List <KeyValuePair <string, object> >)obj)) { GetKnownTypesForInstance(keyValuePair.Value, knownTypeList, alreadyCheckedTypes); } } else if (objectType == typeof(List <PropertyValue>)) { foreach (var propertyValue in ((List <PropertyValue>)obj)) { GetKnownTypesForInstance(propertyValue.Value, knownTypeList, alreadyCheckedTypes); } } // Generic collections are special in Silverlight and WP7 (WHY?!) else if (IsSpecialCollectionType(objectType) && !objectType.IsInterfaceEx()) { AddTypeToKnownTypesIfSerializable(knownTypeList, objectType); } else if (!objectType.FullName.StartsWith("System.")) { var fields = objectType.GetFieldsEx(BindingFlagsHelper.GetFinalBindingFlags(false, false)); foreach (var field in fields) { try { object value = field.GetValue(obj); GetKnownTypes(value == null ? field.FieldType : value.GetType(), knownTypeList, alreadyCheckedTypes); } catch (Exception) { Log.Warning("Failed to get value for field '{0}' of type '{1}'", field.Name, objectType.Name); } } var properties = objectType.GetPropertiesEx(BindingFlagsHelper.GetFinalBindingFlags(false, false)); foreach (var property in properties) { try { object value = property.GetValue(obj, null); GetKnownTypes(value == null ? property.PropertyType : value.GetType(), knownTypeList, alreadyCheckedTypes); } catch (Exception) { Log.Warning("Failed to get value for property '{0}' of type '{1}'", property.Name, objectType.Name); } } } return(knownTypeList.ToArray()); }
/// <summary> /// Gets the key from interface, which is required for MEF. /// </summary> /// <param name="container">The container.</param> /// <param name="interfaceType">Type of the interface.</param> /// <returns>The key based on the interface.</returns> /// <exception cref="ArgumentNullException">The <paramref name="interfaceType"/> is <c>null</c>.</exception> private string GetKeyFromInterface(object container, Type interfaceType) { Argument.IsNotNull("interfaceType", interfaceType); var attributedModelServicesType = GetContainerType("System.ComponentModel.Composition.AttributedModelServices", container); var getContractNameMethodInfo = attributedModelServicesType.GetMethodEx("GetContractName", new[] { typeof(Type) }, BindingFlagsHelper.GetFinalBindingFlags(false, true)); return((string)getContractNameMethodInfo.Invoke(null, new[] { interfaceType })); }