/// <summary>
        /// Eveluates a type and looks for <see cref="DependsOnAttribute"/> attributes, and then applies the <see cref="NotifyChangeAttribute"/> 
        /// to those properties.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="collection">The collection.</param>
        public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
        {
            var targetType = element as Type;
            if (targetType == null) return;

            // Find all properties with a "DependsOn" attribute
            foreach (var originalProperty in targetType.GetProperties())
            {
                var dependsOnAttribute = GetCustomAttribute(originalProperty.GetGetMethod(), typeof(DependsOnAttribute)) as DependsOnAttribute;
                if (dependsOnAttribute == null) continue;

                // Look up the properties listed in the DependsOn attribute. On each on, inject the NotifyChange attribute on its setter, so that when those properties
                // change they will also signal that this property has changed.
                foreach (var affectedByPropertyName in dependsOnAttribute.DependencyPropertyNames)
                {
                    var affectedByPropertyInfo = targetType.GetProperty(affectedByPropertyName);
                    if (affectedByPropertyInfo == null)
                    {
                        throw new Exception(
                            string.Format(
                                "The property '{0}' on type '{1}' is marked as being dependant on sibling property '{2}', but the property '{2}' cannot be found.",
                                originalProperty.Name, originalProperty.DeclaringType, affectedByPropertyName));
                    }
                    var setter = affectedByPropertyInfo.GetSetMethod(true);
                    if (setter == null)
                    {
                        throw new Exception(
                            string.Format(
                                "The property '{0}' on type '{1}' is marked as being dependant on sibling property '{2}', but the property '{2}' does not have a setter.",
                                originalProperty.Name, originalProperty.DeclaringType, affectedByPropertyName));
                    }
                    collection.AddAspect(setter, new NotifyChangeAttribute(originalProperty.Name));
                }
            }
        }
 /// <summary>
 /// Method called at compile time to get individual aspects required by the current compound
 /// aspect.
 /// </summary>
 /// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
 /// the current custom attribute instance is applied.</param>
 /// <param name="collection">Collection of aspects to which individual aspects should be
 /// added.</param>
 public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
 {
     // Get the target type.
     Type targetType = (Type) targetElement;
     // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
     collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceSubAspect());
     // On the type, add a Composition aspect to implement the IEditableObject interface
     //collection.AddAspect(targetType, new AddEditableObjectInterfaceSubAspect());
     // Add a OnMethodBoundaryAspect on each writable non-static property. The implementation of
     // INotifyPropertyChanged.PropertyChanged needs the name of the property (not of the field), so we have to detect
     // changes on the property level, not on the field level. Unfortunately, there is no rule for naming properties and
     // their related fields. Even more, one property could access many fields, or gets its value out of one or
     // more fields. At this point, using an enhancer to add this functionallity is only recomended, as there exixts a design
     // rule, which relates one field to one and only one property and vice versa. Unfortunately, there is no compile time check available.
     // Please be careful!!
     // Personally, I tend to say, that implementing INotifyPropertyChanged is out of the scope of enhancers due to the
     // possibility to pack logic within the properties implementation, which is never under the enhancers control.
     foreach (PropertyInfo pi in targetType.UnderlyingSystemType.GetProperties())
     {
         if (ReferenceEquals(pi.DeclaringType, targetType) && pi.CanWrite)
         {
             MethodInfo mi = pi.GetSetMethod();
             if (!mi.IsStatic)
             {
                 collection.AddAspect(mi, new OnPropertySetSubAspect(pi.Name, this));
             }
         }
     }
 }
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound
        /// aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be
        /// added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            Type targetType = (Type)targetElement;

            Console.WriteLine("Adding aspects to type: " + targetType);

            // On the type, add a Composition aspect to implement the INotifyCollectionChange interface.
            collection.AddAspect(targetType, new AddNotifyCollectionChangeInterfaceAspect(enableLogging));

            Console.WriteLine("Applicable to {0} fields.",
                              targetType.UnderlyingSystemType.GetFields(BindingFlags.Instance | BindingFlags.Public |
                                                                        BindingFlags.NonPublic).Length);
            foreach (var fieldInfo in targetType.UnderlyingSystemType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                Console.WriteLine("Analizing: " + fieldInfo.Name);
                // skip changes of selected fields marked with [NoNotifyPropertyChanged]
                if (IsBackingField(fieldInfo))
                {
                    Console.WriteLine("Analizing backing field: " + fieldInfo.Name);
                    PropertyInfo pi = GetPublicProperty(targetType, fieldInfo);
                    if (pi == null)
                    {
                        Console.WriteLine("Skipping field: {0}, no public property found." + fieldInfo.Name);
                        continue;
                    }
                    if (pi.GetCustomAttributes(typeof(NoNotifyPropertyChangeAttribute), true).Length != 0)
                    {
                        Console.WriteLine("Skipping field: " + fieldInfo.Name);
                        continue;
                    }
                    if (pi.GetCustomAttributes(typeof(NoNotifyCollectionChangedAttribute), true).Length != 0)
                    {
                        Console.WriteLine("Skipping field: " + fieldInfo.Name);
                        continue;
                    }
                }


                object[] attributes = fieldInfo.GetCustomAttributes(typeof(NoNotifyPropertyChangeAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fieldInfo.Name);
                    continue;
                }
                attributes = fieldInfo.GetCustomAttributes(typeof(NoNotifyCollectionChangedAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fieldInfo.Name);
                    continue;
                }

                if (fieldInfo.DeclaringType == targetType && !fieldInfo.IsStatic && fieldInfo.FieldType != typeof(string) && !fieldInfo.FieldType.IsValueType && !TypeUtils.IsDelegate(fieldInfo.FieldType))
                {
                    Console.WriteLine("Intercepting NotifyCollectionChanged aspect for field: " + fieldInfo.Name);
                    collection.AddAspect(fieldInfo, new BubbleNotifyCollectionChangeFieldAspect(this, enableLogging));
                }
            }
        }
Example #4
0
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound
        /// aspect.
        /// </summary>
        /// <param name="element">Metadata element (<see cref="Type"/> in our case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be
        /// added.</param>
        public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            var targetType = (Type)element;

            // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
            collection.AddAspect(targetType, new AddEditableObjectInterfaceSubAspect());
        }
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound
        /// aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be
        /// added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            Type targetType = (Type) targetElement;

            Console.WriteLine("Adding aspects to type: " + targetType);

            // On the type, add a Composition aspect to implement the INotifyCollectionChanged interface.
            collection.AddAspect(targetType, new AddNotifyCollectionChangedInterfaceAspect(enableLogging));

            Console.WriteLine("Applicable to {0} fields.",
                              targetType.UnderlyingSystemType.GetFields(BindingFlags.Instance | BindingFlags.Public |
                                                                        BindingFlags.NonPublic).Length);
            foreach (
                FieldInfo fi in
                    targetType.UnderlyingSystemType.GetFields(BindingFlags.Instance | BindingFlags.Public |
                                                              BindingFlags.NonPublic))
            {
                Console.WriteLine("Analizing: " + fi.Name);
                // skip changes of selected fields marked with [NoNotifyPropertyChanged]
                if (IsBackingField(fi))
                {
                    Console.WriteLine("Analizing backing field: " + fi.Name);
                    PropertyInfo pi = GetProperty(targetType, fi);
                    if (pi.GetCustomAttributes(typeof(NoBubbling), true).Length != 0)
                    {
                        Console.WriteLine("Skipping field: " + fi.Name);
                        continue;
                    }
                    if (pi.GetCustomAttributes(typeof(NoNotifyCollectionChangedAttribute), true).Length != 0)
                    {
                        Console.WriteLine("Skipping field: " + fi.Name);
                        continue;
                    }
                }


                object[] attributes = fi.GetCustomAttributes(typeof (NoBubbling), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fi.Name);
                    continue;
                }
                attributes = fi.GetCustomAttributes(typeof(NoNotifyCollectionChangedAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fi.Name);
                    continue;
                }
                
                if (fi.DeclaringType == targetType && !fi.IsStatic && IsCollection(fi.FieldType) && !TypeUtils.IsDelegate(fi.FieldType))
                {
                    Console.WriteLine("Intercepting NotifyCollectionChanged aspect for field: " + fi.Name);
                    collection.AddAspect(fi, new BubbleNotifyCollectionChangedAspect(this, enableLogging));
                }
            }
        }
 public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
 {
     Type targettype = (Type)element;
       BufferWritesAspect bufferWritesAspect = new BufferWritesAspect();
       foreach (FieldInfo fi in targettype.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
       {
     if (!fi.IsStatic)
     {
       collection.AddAspect(fi, bufferWritesAspect);
     }
       }
 }
Example #7
0
        public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
        {
            Type targettype = (Type)element;
            BufferWritesAspect bufferWritesAspect = new BufferWritesAspect();

            foreach (FieldInfo fi in targettype.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
            {
                if (!fi.IsStatic)
                {
                    collection.AddAspect(fi, bufferWritesAspect);
                }
            }
        }
        /// <summary>
        /// Provides the aspects.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="collection">The collection.</param>
        public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
        {
            var targetType = element as Type;
            if (targetType == null) return;

            var bindings = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly;
            var methods = targetType.GetMethods(bindings).Cast<MethodBase>();
            var ctors = targetType.GetConstructors(bindings).Cast<MethodBase>();
            var membersToValidate = methods.Union(ctors).Where(ShouldValidate);
            foreach (var method in membersToValidate)
            {
                collection.AddAspect(method, new MethodParameterValidationAspect());
            }
        }
Example #9
0
      /// <summary>Invoked at compile time to get the sub-aspects required by the compound change tracking aspect.</summary>
      public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection) {
         // Validate declaration scope
         Type targetType = ((Type)targetElement).UnderlyingSystemType;
         _validateDeclaration(targetType);

         // Compile class 
         BplLanguage.ErrorList.Clear();
         BplLanguage.RuntimeMode = BplRuntimeMode.Compiling;
         var bplClass = BplLanguage.LoadClass(targetType);

         // Check for errors
         if (BplLanguage.ErrorList.Count > 0) {
            
            // Print the BPL error messages
            foreach (var item in BplLanguage.ErrorList.Items) {
               var subject = item.Subject as BplClass;
               if (subject == null || subject.UnderlyingType != targetType) continue;
               var severity = (item.Severity == Severity.Error ? SeverityType.Error : item.Severity == Severity.Warning ? SeverityType.Warning : SeverityType.Info);
               var errorCode = item.ErrorCode.Nvl("BPL0000");
               var errorText = item.Text.Nvl("Unknown BPL error");
               MessageSource.MessageSink.Write(new Message(severity, errorCode, errorText, "BPL"));
            }

         } else if (bplClass != null && bplClass.IsValid) {

            // Add a wrapper for each BPL constructor 
            foreach (var cstor in targetType.GetInstanceConstructors()) {
               collection.AddAspect(cstor, new BplConstructorWrapper(targetType, this));
            }

            // Add a wrapper for each BPL property setter
            foreach (var propInfo in targetType.GetInstanceProperties(true)) {
               var property = bplClass.GetProperty(propInfo);
               if (property != null && !property.IsCalculated) {
                  // TODO: uncomment the following lines after BplTransaction is fully implemented
                  //var getter = propInfo.GetGetMethod(true);
                  //if (getter != null && !getter.IsStatic) {
                  //   collection.AddAspect(getter, new BplGetterWrapper(propInfo.Name, this));
                  //}
                  var setter = propInfo.GetSetMethod(true);
                  if (setter != null && !setter.IsStatic) {
                     collection.AddAspect(setter, new BplSetterWrapper(propInfo.Name, this));
                  }
               }
            }

         }
      }
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound
        /// aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be
        /// added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            Type targetType = (Type)targetElement;

            // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
            collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceAdvice());

            // Add a OnMethodBoundaryAspect on each writable non-static property.
            foreach (PropertyInfo property in
                     from PropertyInfo p in targetType.UnderlyingSystemType.GetProperties()
                     where p.DeclaringType == targetType &&
                     p.CanWrite &&
                     !p.GetSetMethod(true).IsStatic
                     select p)
            {
                collection.AddAspect(property.GetSetMethod(true), new OnPropertySetAdvice(property.Name, this));
            }
        }
        /// <summary>
        /// Provides the aspects.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="collection">The collection.</param>
        public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
        {
            var targetType = element as Type;

            if (targetType == null)
            {
                return;
            }

            var bindings          = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly;
            var methods           = targetType.GetMethods(bindings).Cast <MethodBase>();
            var ctors             = targetType.GetConstructors(bindings).Cast <MethodBase>();
            var membersToValidate = methods.Union(ctors).Where(ShouldValidate);

            foreach (var method in membersToValidate)
            {
                collection.AddAspect(method, new MethodParameterValidationAspect());
            }
        }
Example #12
0
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            Type targetType = (Type)targetElement;

            // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
            collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceSubAspect());

            // Add a OnMethodBoundaryAspect on each writable non-static property.
            foreach (PropertyInfo property in targetType.GetProperties())
            {
                if (property.DeclaringType == targetType && property.CanWrite)
                {
                    MethodInfo method = property.GetSetMethod();
                    if (!method.IsStatic)
                    {
                        collection.AddAspect(method, new OnPropertySetSubAspect(property.Name, this));
                    }
                }
            }
        }
 public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection) 
 { 
     // Get the target type. 
     Type targetType = (Type)targetElement; 
     
     // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface. 
     collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceSubAspect()); 
     
     // Add a OnMethodBoundaryAspect on each writable non-static property. 
     foreach (PropertyInfo property in targetType.GetProperties()) 
     { 
         if (property.DeclaringType == targetType && property.CanWrite ) 
         { 
             MethodInfo method = property.GetSetMethod(); 
             if (!method.IsStatic) 
             { 
                 collection.AddAspect(method, new OnPropertySetSubAspect(property.Name, this)); 
             } 
         } 
     } 
 } 
Example #14
0
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in this case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type
            Type type = (Type)targetElement;

            // Add an aspect to track the graph instance for each real instance
            collection.AddAspect(type, InjectionGraphTypeProvider.GetInstanceAspect());

            // Add aspects to track interactions with all public properties
            foreach (PropertyInfo property in type.UnderlyingSystemType.GetProperties())
            {
                // Only consider properties declared on this type that can be read, are not static, and either can be set or are mutable lists
                if (property.DeclaringType == type && property.CanRead && !property.GetGetMethod().IsStatic && (property.CanWrite || typeof(IList).IsAssignableFrom(property.PropertyType)))
                {
                    collection.AddAspect(property.GetGetMethod(), InjectionGraphTypeProvider.GetOnPropertyGetAspect(property));

                    // Only add aspects to setters for writable properties
                    if (property.CanWrite)
                        collection.AddAspect(property.GetSetMethod(true), InjectionGraphTypeProvider.GetOnPropertySetAspect(property));
                }
            }
        }
Example #15
0
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in this case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type
            Type type = (Type)targetElement;

            // Add an aspect to track the graph instance for each real instance
            collection.AddAspect(type, InjectionGraphTypeProvider.GetInstanceAspect());

            // Add aspects to track interactions with all public properties
            foreach (PropertyInfo property in type.UnderlyingSystemType.GetProperties())
            {
                // Only consider properties declared on this type that can be read, are not static, and either can be set or are mutable lists
                if (property.DeclaringType == type && property.CanRead && !property.GetGetMethod().IsStatic&& (property.CanWrite || typeof(IList).IsAssignableFrom(property.PropertyType)))
                {
                    collection.AddAspect(property.GetGetMethod(), InjectionGraphTypeProvider.GetOnPropertyGetAspect(property));

                    // Only add aspects to setters for writable properties
                    if (property.CanWrite)
                    {
                        collection.AddAspect(property.GetSetMethod(true), InjectionGraphTypeProvider.GetOnPropertySetAspect(property));
                    }
                }
            }
        }
Example #16
0
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound
        /// aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be
        /// added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            Type targetType = (Type)targetElement;

            Console.WriteLine("Adding aspects to type: " + targetType);

            // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
            collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceAspect(enableLogging));

            // Add a OnMethodBoundaryAspect on each writable non-static property.
            foreach (PropertyInfo property in targetType.UnderlyingSystemType.GetProperties())
            {
                object[] attributes = property.GetCustomAttributes(typeof(NoNotifyPropertyChangedAttribute), true);
                // skip changes of selected properties marked with [NoNotifyPropertyChanged]
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping property: " + property.Name);
                    continue;
                }

                attributes = property.GetCustomAttributes(typeof(NoBubbling), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping property: " + property.Name);
                    continue;
                }

                if (property.DeclaringType == targetType && property.CanWrite)
                {
                    MethodInfo method = property.GetSetMethod();

                    if (method != null && !method.IsStatic)
                    {
                        Console.WriteLine("Intercepting NotifyPropertyChanged aspect for property: " + property.Name);
                        collection.AddAspect(method,
                                             new OnNotifyPropertyChangedAspect(property.Name, this, enableLogging));
                    }
                }
            }

            //todo exclude: eventhandlers from subscription
            foreach (
                FieldInfo fi in
                targetType.UnderlyingSystemType.GetFields(BindingFlags.Instance | BindingFlags.Public |
                                                          BindingFlags.NonPublic))
            {
                object[] attributes = fi.GetCustomAttributes(typeof(NoNotifyPropertyChangedAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fi.Name);
                    continue;
                }

                attributes = fi.GetCustomAttributes(typeof(NoBubbling), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fi.Name);
                    continue;
                }

                if (fi.DeclaringType == targetType && !fi.IsStatic && !fi.FieldType.IsValueType &&
                    fi.FieldType != typeof(string) && !TypeUtils.IsDelegate(fi.FieldType))
                {
                    //only apply to field setter, not to getter.
                    Console.WriteLine("Intercepting NotifyPropertyChanged aspect for field: " + fi.Name + " bubbling");
                    collection.AddAspect(fi, new BubbleNotifyPropertyChangedAspect(fi.Name, this, enableLogging));
                }
            }
        }
        /// <summary>
        /// Ordnet dem Elementtyp den passenden Aspekt zu.
        /// </summary>
        /// <param name="element">Element für welches ein Kontrakt vorliegt.</param>
        /// <param name="collection">Liste mit den Aspekten</param>
        public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
        {
            if (!(element is MemberInfo))
            {
                CreateCompilerError(string.Format(Resources.ExcElementisNoMemberInfo, new object[]{element}), null);
                return;
            }
            try
            {
                // Hier werden alle Elemente übergeben, die einen Kontrakt definieren,
                // für Eigenschaften und dessen get bzw. set Methode erfolgt einen Aufruf
                // dieser Redundante Aufruf wird hier verhindert.
                if ((!AspectController.Instance.CanAttachAspectToMember((MemberInfo)element))
                    || ((element is MethodInfo) && (((MethodInfo)element).IsSpecialName)))
                    return;
                CheckContracts((MemberInfo)element, mContracts);

                if (element is PropertyInfo)
                    AddAspectToProperty(mContracts, collection, (PropertyInfo)element);
                else if (element is MethodInfo)
                    AddAspectToMethod(mContracts, collection, (MethodInfo)element);
                else if (element is FieldInfo)
                    AddAspectToField(mContracts, collection, (FieldInfo)element);

            }
            catch(Exception exception)
            {
                CreateCompilerError(exception.ToString(), (MemberInfo)element);
            }
        }
        /// <summary>
        /// Fügt einem Feld den Contract Aspekt hinzu.
        /// </summary>
        /// <param name="contractList">Liste mit den übergebenen Kontrakten.</param>
        /// <param name="aspectCollection">Collection mit allen Membern denen der Aspekt zugewiesen wurde.</param>
        /// <param name="method">FieldInfo Objekt des Feldes an dem der Kontrakt definiert wurde.</param>
        private void AddAspectToField(List<string> contractList, LaosReflectionAspectCollection aspectCollection, FieldInfo field)
        {
            // Klassennamen erzeugen
            string contractClassName = AspectController.Instance.CreateContractClassName(field.DeclaringType.Assembly);

            FieldModel fieldModel = null;

            // Kontraktmodell erzeugen:
            string getContract = string.Empty;
            string setContract = string.Empty;
            if (contractList.Count == 2)
            {
                getContract = contractList[0];
                setContract = contractList[1];
            }
            else if (contractList.Count == 1)
            {
                getContract = contractList[0];
                setContract = contractList[0];
            }

            switch (DbcAccessType)
            {
                case AccessType.OnlyOnGet:
                    fieldModel = new FieldModel(getContract, string.Empty, field, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                    break;
                case AccessType.OnlyOnSet:
                    fieldModel = new FieldModel(string.Empty, setContract, field, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                    break;
                default:
                    fieldModel = new FieldModel(getContract, setContract, field, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                    break;
            }

            aspectCollection.AddAspect(field, new FieldAccessAspect(fieldModel));
        }
        /// <summary>
        /// Fügt einer Methode den Contract Aspekt hinzu.
        /// </summary>
        /// <param name="contractList">Liste mit den übergebenen Kontrakten.</param>
        /// <param name="aspectCollection">Collection mit allen Membern denen der Aspekt zugewiesen wurde.</param>
        /// <param name="method">MethodInfo Objekt der Methode an der der Kontrakt definiert wurde.</param>
        private void AddAspectToMethod(List<string> contractList, LaosReflectionAspectCollection aspectCollection, MethodInfo method)
        {
            // Klassennamen erzeugen
            string contractClassName = AspectController.Instance.CreateContractClassName(method.DeclaringType.Assembly);

            MethodModel contractModel = null;

            // Kontraktmodell erzeugen:
            string requireContract = string.Empty;
            string ensureContract = string.Empty;
            if (contractList.Count == 2)
            {
                requireContract = contractList[0];
                ensureContract = contractList[1];
            }
            else if (contractList.Count == 1)
            {
                requireContract = contractList[0];
                ensureContract = contractList[0];
            }

            switch (DbcCheckTime)
            {
                case CheckTime.OnlyRequire:
                    contractModel = new MethodModel(requireContract, string.Empty, method, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                    break;
                case CheckTime.OnlyEnsure:
                    contractModel = new MethodModel(string.Empty, ensureContract, method, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                    break;
                default:
                    contractModel = new MethodModel(requireContract, ensureContract, method, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                    break;
            }

            aspectCollection.AddAspect(method, new MethodBoundaryAspect(contractModel));
        }
        /// <summary>
        /// Fügt einer Eigenschaft den Contract Aspekt hinzu.
        /// </summary>
        /// <param name="contractList">Liste mit den übergebenen Kontrakten.</param>
        /// <param name="aspectCollection">Collection mit allen Membern denen der Aspekt zugewiesen wurde.</param>
        /// <param name="property">PropertyInfo Objekt der Eigenschaft an der der Kontrakt definiert wurde.</param>
        private void AddAspectToProperty(List<string> contractList, LaosReflectionAspectCollection aspectCollection, PropertyInfo property)
        {
            // Klassennamen erzeugen
            string contractClassName = AspectController.Instance.CreateContractClassName(property.DeclaringType.Assembly);

            MethodModel getContractModel = null;
            MethodModel setContractModel = null;

            // Kontraktmodelle erzeugen:
            if (contractList.Count == 4)
            {

                setContractModel = new MethodModel(contractList[0], contractList[2], property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                getContractModel = new MethodModel(contractList[1], contractList[3], property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
            }
            else
            {
                string requireContract = string.Empty;
                string ensureContract = string.Empty;
                if (contractList.Count == 2)
                {
                    requireContract = contractList[0];
                    ensureContract = contractList[1];
                }
                else if (contractList.Count == 1)
                {
                    requireContract = contractList[0];
                    ensureContract = contractList[0];
                }

                switch (DbcCheckTime)
                {
                    case CheckTime.OnlyRequire:
                        setContractModel = new MethodModel(requireContract, string.Empty, property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                        getContractModel = new MethodModel(requireContract, string.Empty, property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                        break;
                    case CheckTime.OnlyEnsure:
                        setContractModel = new MethodModel(string.Empty, ensureContract, property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                        getContractModel = new MethodModel(string.Empty, ensureContract, property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                        break;
                    default:
                        setContractModel = new MethodModel(requireContract, ensureContract, property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                        getContractModel = new MethodModel(requireContract, ensureContract, property, DbcAccessType, DbcCheckTime, contractClassName, DbcExceptionType, DbcExceptionString);
                        break;
                }
            }

            // Die Aspekte den Get bzw. Set Methoden zuweisen.

            if ((property.GetGetMethod(true) != null) && (DbcAccessType != AccessType.OnlyOnSet))
                aspectCollection.AddAspect(property.GetGetMethod(true), new MethodBoundaryAspect(getContractModel));

            if ((property.GetSetMethod(true) != null) && (DbcAccessType != AccessType.OnlyOnGet))
                aspectCollection.AddAspect(property.GetSetMethod(true), new MethodBoundaryAspect(setContractModel));
        }
Example #21
0
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound
        /// aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be
        /// added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            Type targetType = (Type)targetElement;

            Console.WriteLine("Adding aspects to type: " + targetType);

            // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
            collection.AddAspect(targetType, new AddNotifyPropertyChangeInterfaceAspect(enableLogging));

            var interceptedPropertyNames = new List <string>();

            // Add a OnMethodBoundaryAspect on each writable non-static property.
            foreach (var propertyInfo in targetType.UnderlyingSystemType.GetProperties())
            {
                var attributes = propertyInfo.GetCustomAttributes(typeof(NoNotifyPropertyChangeAttribute), true);
                // skip changes of selected properties marked with [NoNotifyPropertyChanged]
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping property: " + propertyInfo.Name);
                    continue;
                }

                attributes = propertyInfo.GetCustomAttributes(typeof(NoNotifyPropertyChangeAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping property: " + propertyInfo.Name);
                    continue;
                }

                if (propertyInfo.DeclaringType == targetType && propertyInfo.CanWrite)
                {
                    //private set method is OK
                    MethodInfo setMethod = propertyInfo.GetSetMethod(true); //private setter is OK
                    MethodInfo getMethod = propertyInfo.GetGetMethod();     //getter should be public


                    if (getMethod != null && setMethod != null && !setMethod.IsStatic)
                    {
                        Console.WriteLine("Intercepting NotifyPropertyChanged aspect for property: " + propertyInfo.Name);

                        collection.AddAspect(setMethod, new NotifyPropertyChangeAspect(propertyInfo.Name, this, enableLogging));

                        interceptedPropertyNames.Add(propertyInfo.Name.ToLower());
                    }
                }
            }

            //todo exclude: eventhandlers from subscription
            foreach (var fieldInfo in targetType.UnderlyingSystemType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                if (!interceptedPropertyNames.Any(n => fieldInfo.Name.ToLower().Equals(n) || fieldInfo.Name.ToLower().Contains("<" + n)))
                {
                    Console.WriteLine("Skipping field: " + fieldInfo.Name + " (no property intercepted)");
                    continue;
                }

                // skip subscription if field is not of an interface type and not subscribable
                if (fieldInfo.FieldType.IsValueType)
                {
                    Console.WriteLine("Skipping field: " + fieldInfo.Name + " (does not implement INotifyPropertyChanged)");
                    continue;
                }

                var attributes = fieldInfo.GetCustomAttributes(typeof(NoNotifyPropertyChangeAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fieldInfo.Name);
                    continue;
                }

                attributes = fieldInfo.GetCustomAttributes(typeof(NoNotifyPropertyChangeAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fieldInfo.Name);
                    continue;
                }

                if (fieldInfo.DeclaringType == targetType && !fieldInfo.IsStatic && !fieldInfo.FieldType.IsValueType &&
                    fieldInfo.FieldType != typeof(string) && !TypeUtils.IsDelegate(fieldInfo.FieldType))
                {
                    //only apply to field setter, not to getter.
                    Console.WriteLine("Intercepting NotifyPropertyChanged aspect for field: " + fieldInfo.Name + " bubbling");
                    collection.AddAspect(fieldInfo, new BubblePropertyChangeFieldAspect(fieldInfo.Name, this, enableLogging));
                }
            }
        }
        /// <summary>
        /// Method called at compile time to get individual aspects required by the current compound
        /// aspect.
        /// </summary>
        /// <param name="targetElement">Metadata element (<see cref="Type"/> in our case) to which
        /// the current custom attribute instance is applied.</param>
        /// <param name="collection">Collection of aspects to which individual aspects should be
        /// added.</param>
        public override void ProvideAspects(object targetElement, LaosReflectionAspectCollection collection)
        {
            // Get the target type.
            Type targetType = (Type) targetElement;

            Console.WriteLine("Adding aspects to type: " + targetType);

            // On the type, add a Composition aspect to implement the INotifyPropertyChanged interface.
            collection.AddAspect(targetType, new AddNotifyPropertyChangedInterfaceAspect(enableLogging));

            // Add a OnMethodBoundaryAspect on each writable non-static property.
            foreach (PropertyInfo property in targetType.UnderlyingSystemType.GetProperties())
            {
                object[] attributes = property.GetCustomAttributes(typeof (NoNotifyPropertyChangedAttribute), true);
                // skip changes of selected properties marked with [NoNotifyPropertyChanged]
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping property: " + property.Name);
                    continue;
                }

                attributes = property.GetCustomAttributes(typeof(NoBubbling), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping property: " + property.Name);
                    continue;
                }

                if (property.DeclaringType == targetType && property.CanWrite)
                {
                    MethodInfo method = property.GetSetMethod();

                    if (method != null && !method.IsStatic)
                    {
                        Console.WriteLine("Intercepting NotifyPropertyChanged aspect for property: " + property.Name);
                        collection.AddAspect(method,
                                             new OnNotifyPropertyChangedAspect(property.Name, this, enableLogging));
                    }
                }
            }

            //todo exclude: eventhandlers from subscription
            foreach (
                FieldInfo fi in
                    targetType.UnderlyingSystemType.GetFields(BindingFlags.Instance | BindingFlags.Public |
                                                              BindingFlags.NonPublic))
            {
                object[] attributes = fi.GetCustomAttributes(typeof(NoNotifyPropertyChangedAttribute), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fi.Name);
                    continue;
                }

                attributes = fi.GetCustomAttributes(typeof(NoBubbling), true);
                if (attributes.Length != 0)
                {
                    Console.WriteLine("Skipping field: " + fi.Name);
                    continue;
                }

                if (fi.DeclaringType == targetType && !fi.IsStatic && !fi.FieldType.IsValueType &&
                    fi.FieldType != typeof (string) && !TypeUtils.IsDelegate(fi.FieldType))
                {
                    //only apply to field setter, not to getter.
                    Console.WriteLine("Intercepting NotifyPropertyChanged aspect for field: " + fi.Name + " bubbling");
                    collection.AddAspect(fi, new BubbleNotifyPropertyChangedAspect(fi.Name, this, enableLogging));
                }
            }
        }