/// <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)); } } }
/// <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="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)); } } }
/// <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)); } }
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 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); } } }
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)); } } } }
/// <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)); } } }
/// <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()); } }
/// <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)); } } } }
/// <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()); } }
/// <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; 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> /// 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)); }
/// <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)); } } }