void IPropertyAdvice.Advise(PropertyAdviceContext context)
        {
            var ctx = BeforeProcessing(new ActivationContext(context));

            if (ctx.ExecuteAlternate)
            {
                if (context.IsGetter && ctx.SkipTargetProcess)
                {
                    var task = AlternateProceed(ctx);
                    context.Value = task;
                }
                else
                {
                    AlternateProceed(ctx);
                }
            }
            if (!ctx.SkipTargetProcess)
            {
                try
                {
                    context.Proceed();
                }
                catch (Exception ex)
                {
                    HandleException(ctx, ex);
                    throw;
                }
            }
            ctx = AfterProcesssing(ctx);
            ctx.Clean();
        }
예제 #2
0
 public void Advise(PropertyAdviceContext context)
 {
     using (var t = TracerFactory.StartTracer(context.TargetType, string.Format("{0}_{1}", context.IsGetter ? "get" : "set", context.TargetProperty.Name)))
     {
         if (info.ContainsCharacters())
         {
             t.SetAdidtionalInformation(info);
         }
         try
         {
             context.Proceed();
         }
         catch (Exception ex)
         {
             if (TreatExceptionAsInformational)
             {
                 t.SetException(ex);
             }
             else
             {
                 t.SetErrorState(ex);
             }
             throw;
         }
     }
 }
예제 #3
0
 public void Advise(PropertyAdviceContext context)
 {
     if (context.IsGetter)
     {
         context.ReturnValue = _value;
     }
     else
     {
         _value = context.Value;
     }
 }
        public void Advise(PropertyAdviceContext context)
        {
            if (context.HasValue)
            {
                if (context.Value != null && context.Value.ToString().ToLower() == "null")
                {
                    context.Value = null;
                }
            }

            context.Proceed();
        }
예제 #5
0
        public void Advise(PropertyAdviceContext context)
        {
            // some non-sense mocking
            if (context.IsGetter)
            {
                context.ReturnValue = Activator.CreateInstance(context.TargetProperty.PropertyType);
            }

            // now, some advice
            if (NewReturnValue.HasValue)
            {
                context.ReturnValue = NewReturnValue.Value;
            }
        }
예제 #6
0
        /// <summary>
        /// Advises the specified property.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Advise(PropertyAdviceContext context)
        {
            var targetProperty        = context.TargetProperty;
            var persistenceSerializer = Configuration.GetSerializer(targetProperty);
            var persistenceData       = Configuration.GetData(targetProperty);

            if (context.IsGetter)
            {
                context.ReturnValue = persistenceData.GetValue(Name, targetProperty.PropertyType, DefaultValue, persistenceSerializer);
            }
            else
            {
                persistenceData.SetValue(Name, context.Value, targetProperty.PropertyType, AutoSave, persistenceSerializer);
            }
        }
예제 #7
0
 /// <summary>
 /// 拦截属性
 /// </summary>
 /// <param name="context">属性上下文</param>
 public void Advise(PropertyAdviceContext context)
 {
     if (context.IsGetter)
     {
         context.Proceed();
     }
     else
     {
         context.Proceed();
         if (context.Target is INotifyPropertyChangedEx dataContext)
         {
             dataContext.NotifyOfPropertyChange(context.TargetName);
         }
     }
 }
예제 #8
0
        public void Advise(PropertyAdviceContext context)
        {
            if (_persistenceProperty == null)
            {
                _persistenceProperty = new PropertyImporter <IPersistence>(context.TargetProperty.DeclaringType);
            }
            var persistence = _persistenceProperty.Get(context.Target);

            if (context.IsGetter)
            {
                context.ReturnValue = persistence.GetValue(Name, context.TargetProperty.PropertyType, DefaultValue);
            }
            else
            {
                persistence.SetValue(Name, context.Value, AutoSave);
            }
        }
예제 #9
0
 /// <summary>
 /// Implements advice logic.
 ///             Usually, advice must invoke context.Proceed()
 /// </summary>
 /// <param name="context">The method advice context.</param>
 void IPropertyAdvice.Advise(PropertyAdviceContext context)
 {
     if (context.IsSetter && context.Value == null)
     {
         Logging.DebugMessage("Property '{0}' cannot be null on '{1}'{2}Parent object: {2}{3}", context.TargetProperty.Name, context.TargetType.FullName, Environment.NewLine, context.Target == null ? "" : context.Target.ToString());
         throw new ArgumentNullException(context.TargetProperty.Name, string.Format("Property '{0}' cannot be null on '{1}'", context.TargetProperty.Name, context.TargetType.FullName));
     }
     context.Proceed();
     if (context.IsGetter && CheckOnGet && (!context.HasReturnValue || context.ReturnValue == null))
     {
         Logging.DebugMessage("Property '{0}' cannot be null on '{1}'{2}Parent object: {2}{3}", context.TargetProperty.Name, context.TargetType.FullName, Environment.NewLine, context.Target == null ? "" : context.Target.ToString());
         if (ThrowOnGet)
         {
             throw new ArgumentNullException(context.TargetProperty.Name, string.Format("Property '{0}' cannot be null on '{1}'", context.TargetProperty.Name, context.TargetType.FullName));
         }
     }
 }
예제 #10
0
 void IPropertyAdvice.Advise(PropertyAdviceContext context)
 {
     try
     {
         context.Proceed();
     }
     catch (NullReferenceException ex)
     {
         ex.Log(string.Format("Null reference in {2}.{0}.[{1}]", context.TargetProperty.Name, context.IsGetter ? "get" : "set", context.TargetType.FullName));
         throw;
     }
     catch (Exception ex)
     {
         ex.Log(context.IsGetter ? "Getter" : "Setter");
         throw;
     }
 }
        public void Advise(PropertyAdviceContext propertyContext)
        {
            var classType    = propertyContext.TargetType;
            var propertyType = propertyContext.TargetProperty;

            if (!classType.IsSameOrSubclassOf(typeof(ObservableObject)))
            {
                throw new InvalidProgramException($"The Attribute {GetType().FullName} is not applicable to {classType.FullName}. {classType.FullName} must derived from {nameof(ObservableObject)}.");
            }

            // Getter
            if (propertyContext.IsGetter)
            {
                propertyContext.Proceed();
                return;
            }

            // Setter
            propertyContext.Proceed();
            (propertyContext.Target as ObservableObject).InvokePropertyChanged(propertyType.Name);
        }
예제 #12
0
        private static AdviceContext CreateAdviceContext(AdviceValues adviceValues, AspectInfo aspectInfo)
        {
            AdviceContext adviceContext = new InnerMethodContext(adviceValues, aspectInfo.PointcutMethod, aspectInfo.PointcutMethodDelegate);

            for (var adviceIndex = aspectInfo.Advices.Count - 1; adviceIndex >= 0; adviceIndex--)
            {
                var advice = aspectInfo.Advices[adviceIndex];
                // aspects are processed from highest to lowest level, so they are linked here in the opposite order
                // 3. as parameter
                if (advice.ParameterAdvice != null && advice.ParameterIndex.HasValue)
                {
                    var parameterIndex = advice.ParameterIndex.Value;
                    var parameterInfo  = GetParameterInfo(aspectInfo.AdvisedMethod, parameterIndex);
                    adviceContext = new ParameterAdviceContext(advice.ParameterAdvice, parameterInfo, parameterIndex, adviceValues, adviceContext);
                }
                // 2. as method
                if (advice.MethodAdvice != null)
                {
                    adviceContext = new MethodAdviceContext(advice.MethodAdvice, aspectInfo.AdvisedMethod, adviceValues, adviceContext);
                }
                // 2b. as async method
                if (advice.AsyncMethodAdvice != null)
                {
                    adviceContext = new MethodAsyncAdviceContext(advice.AsyncMethodAdvice, aspectInfo.AdvisedMethod, adviceValues, adviceContext);
                }
                // 1. as property
                if (advice.PropertyAdvice != null && aspectInfo.PointcutProperty != null)
                {
                    adviceContext = new PropertyAdviceContext(advice.PropertyAdvice, aspectInfo.PointcutProperty, aspectInfo.IsPointcutPropertySetter, adviceValues, adviceContext);
                }
                // 1b. as event
                if (advice.EventAdvice != null && aspectInfo.PointcutEvent != null)
                {
                    adviceContext = new EventAdviceContext(advice.EventAdvice, aspectInfo.PointcutEvent, aspectInfo.IsPointcutEventAdder, adviceValues, adviceContext);
                }
            }

            return(adviceContext);
        }
        public void Advise(PropertyAdviceContext propertyContext)
        {
            var classInstance = propertyContext.Target;
            var classType     = propertyContext.TargetType;
            var propertyType  = propertyContext.TargetProperty;

            if (!classType.HasProperty(PropertyName))
            {
                throw new InvalidProgramException($"The class {classType.FullName} doesn't have the property {PropertyName}.");
            }

            var bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;

            var proxyPropertyName = ProxyPropertyName ?? propertyType.Name;
            var property          = classType.GetProperty(PropertyName, bindingFlags);
            var proxyPropetyType  = property.PropertyType;

            if (!proxyPropetyType.HasProperty(proxyPropertyName))
            {
                throw new InvalidProgramException($"The class {proxyPropetyType.FullName} of property {PropertyName} doesn't have the property {proxyPropertyName}.");
            }

            var propertyValue           = property.GetValue(classInstance);
            var propertyOfProxyProperty = proxyPropetyType.GetProperty(proxyPropertyName, bindingFlags);

            // Getter
            if (propertyContext.IsGetter)
            {
                propertyContext.Proceed();
                propertyContext.ReturnValue = propertyOfProxyProperty.GetValue(propertyValue);
                return;
            }

            // Setter
            propertyOfProxyProperty.SetValue(propertyValue, propertyContext.Value);
            propertyContext.Proceed();
        }
예제 #14
0
        /// <summary>
        /// Runs a method interception.
        /// We use a static method here, if one day we want to reuse Invocations or change mecanism,
        /// it will be easier from C# code
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="methodHandle">The method handle.</param>
        /// <param name="innerMethodHandle">The inner method handle.</param>
        /// <param name="delegatableMethodHandle">The delegatable method handle.</param>
        /// <param name="typeHandle">The type handle.</param>
        /// <param name="abstractedTarget">if set to <c>true</c> [abstracted target].</param>
        /// <param name="genericArguments">The generic arguments (to static type and/or method) in a single array.</param>
        /// <returns></returns>
        // ReSharper disable once UnusedMember.Global
        // ReSharper disable once UnusedMethodReturnValue.Global
        public static object ProceedAdvice2(object target, object[] parameters, RuntimeMethodHandle methodHandle, RuntimeMethodHandle innerMethodHandle,
                                            RuntimeMethodHandle delegatableMethodHandle, RuntimeTypeHandle typeHandle, bool abstractedTarget, Type[] genericArguments)
        {
            var aspectInfo = GetAspectInfo(methodHandle, innerMethodHandle, delegatableMethodHandle, typeHandle, abstractedTarget, genericArguments);

            // this is the case with auto implemented interface
            if (target is AdvisedInterface advisedInterface)
            {
                aspectInfo = aspectInfo.AddAdvice(new AdviceInfo(advisedInterface.Advice));
            }

            foreach (var advice in aspectInfo.Advices)
            {
                InjectIntroducedFields(advice, aspectInfo.AdvisedMethod.DeclaringType);
            }

            // from here, we build an advice chain, with at least one final advice: the one who calls the method
            var adviceValues = new AdviceValues(target, aspectInfo.AdvisedMethod.DeclaringType, parameters);
            // at least there is one context
            AdviceContext adviceContext = new InnerMethodContext(adviceValues, aspectInfo.PointcutMethod, aspectInfo.PointcutMethodDelegate);

            for (var adviceIndex = aspectInfo.Advices.Count - 1; adviceIndex >= 0; adviceIndex--)
            {
                var advice = aspectInfo.Advices[adviceIndex];
                // aspects are processed from highest to lowest level, so they are linked here in the opposite order
                // 3. as parameter
                if (advice.ParameterAdvice != null && advice.ParameterIndex.HasValue)
                {
                    var parameterIndex = advice.ParameterIndex.Value;
                    var parameterInfo  = GetParameterInfo(aspectInfo.AdvisedMethod, parameterIndex);
                    adviceContext = new ParameterAdviceContext(advice.ParameterAdvice, parameterInfo, parameterIndex, adviceValues, adviceContext);
                }
                // 2. as method
                if (advice.MethodAdvice != null)
                {
                    adviceContext = new MethodAdviceContext(advice.MethodAdvice, aspectInfo.AdvisedMethod, adviceValues, adviceContext);
                }
                // 2b. as async method
                if (advice.AsyncMethodAdvice != null)
                {
                    adviceContext = new MethodAsyncAdviceContext(advice.AsyncMethodAdvice, aspectInfo.AdvisedMethod, adviceValues, adviceContext);
                }
                // 1. as property
                if (advice.PropertyAdvice != null && aspectInfo.PointcutProperty != null)
                {
                    adviceContext = new PropertyAdviceContext(advice.PropertyAdvice, aspectInfo.PointcutProperty, aspectInfo.IsPointcutPropertySetter, adviceValues, adviceContext);
                }
                // 1b. as event
                if (advice.EventAdvice != null && aspectInfo.PointcutEvent != null)
                {
                    adviceContext = new EventAdviceContext(advice.EventAdvice, aspectInfo.PointcutEvent, aspectInfo.IsPointcutEventAdder, adviceValues, adviceContext);
                }
            }

            // if the method is no task, then we return immediately
            // (and the adviceTask is completed)
            var adviceTask = adviceContext.Invoke();

            var advisedMethodInfo = aspectInfo.AdvisedMethod as MethodInfo;
            var returnType        = advisedMethodInfo?.ReturnType;

            // no Task means aspect was sync, so everything already ended
            // or it may also been an async void, meaning that we don't care about it
            if (adviceTask == null || returnType == null || !typeof(Task).GetAssignmentReader().IsAssignableFrom(returnType))
            {
                adviceTask?.Wait();
                return(adviceValues.ReturnValue);
            }

            // otherwise, see if it is a Task or Task<>

            // Task is simple too: the advised method is a subtask,
            // so the advice is completed after the method is completed too
            if (returnType == typeof(Task))
            {
                return(adviceTask);
            }

            // only Task<> left here
            var taskType = returnType.GetTaskType();

            // a reflection equivalent of ContinueWith<TNewResult>, but this TNewResult, under taskType is known only at run-time
            return(adviceTask.ContinueWith(t => GetResult(t, adviceValues), taskType));
        }
예제 #15
0
 public void Advise(PropertyAdviceContext context)
 {
     context.Proceed();
 }
예제 #16
0
        /// <summary>
        /// Runs a method interception.
        /// We use a static method here, if one day we want to reuse Invocations or change mecanism,
        /// it will be easier from C# code
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="methodBase">The raw method base.</param>
        /// <param name="innerMethod">The inner method.</param>
        /// <param name="abstractedTarget">if set to <c>true</c> [abstracted target].</param>
        /// <param name="genericArguments">The generic arguments (to static type and/or method) in a single array.</param>
        /// <returns></returns>
        // ReSharper disable once UnusedMember.Global
        // ReSharper disable once UnusedMethodReturnValue.Global
        public static object ProceedAdvice(object target, object[] parameters, MethodBase methodBase, MethodBase innerMethod, bool abstractedTarget, Type[] genericArguments)
        {
            var aspectInfo = GetAspectInfo(methodBase, innerMethod, abstractedTarget, genericArguments);

            // this is the case with auto implemented interface
            var advisedInterface = target as AdvisedInterface;

            if (advisedInterface != null)
            {
                aspectInfo = aspectInfo.AddAdvice(new AdviceInfo(advisedInterface.Advice));
            }

            foreach (var advice in aspectInfo.Advices.Select(a => a.Advice).Distinct())
            {
                InjectIntroducedFields(advice, methodBase.DeclaringType);
            }

            // from here, we build an advice chain, with at least one final advice: the one who calls the method
            var adviceValues = new AdviceValues(target, aspectInfo.AdvisedMethod.DeclaringType, parameters);
            // at least there is one context
            AdviceContext adviceContext = new InnerMethodContext(adviceValues, aspectInfo.PointcutMethod);

            foreach (var advice in aspectInfo.Advices.Reverse())
            {
                // aspects are processed from highest to lowest level, so they are linked here in the opposite order
                // 3. as parameter
                if (advice.ParameterAdvice != null && advice.ParameterIndex.HasValue)
                {
                    var parameterIndex = advice.ParameterIndex.Value;
                    var parameterInfo  = GetParameterInfo(aspectInfo.AdvisedMethod, parameterIndex);
                    adviceContext = new ParameterAdviceContext(advice.ParameterAdvice, parameterInfo, parameterIndex, adviceValues, adviceContext);
                }
                // 2. as method
                if (advice.MethodAdvice != null)
                {
                    adviceContext = new MethodAdviceContext(advice.MethodAdvice, aspectInfo.AdvisedMethod, adviceValues, adviceContext);
                }
                // 2b. as async method
                if (advice.AsyncMethodAdvice != null)
                {
                    adviceContext = new MethodAsyncAdviceContext(advice.AsyncMethodAdvice, aspectInfo.AdvisedMethod, adviceValues, adviceContext);
                }
                // 1. as property
                if (advice.PropertyAdvice != null && aspectInfo.PointcutProperty != null)
                {
                    adviceContext = new PropertyAdviceContext(advice.PropertyAdvice, aspectInfo.PointcutProperty, aspectInfo.IsPointcutPropertySetter, adviceValues, adviceContext);
                }
            }

            // if the method is no task, then we return immediately
            // (and the adviceTask is completed)
            var adviceTask = adviceContext.Invoke();

            var advisedMethodInfo = aspectInfo.AdvisedMethod as MethodInfo;
            var returnType        = advisedMethodInfo?.ReturnType;

            // no Task means aspect was sync, so everything already ended
            // TODO: this is actually not true, since an async method can be void :frown:
            if (adviceTask == null || returnType == null || !typeof(Task).IsAssignableFrom(returnType))
            {
                adviceTask?.Wait();
                return(adviceValues.ReturnValue);
            }

            // otherwise, see if it is a Task or Task<>

            // Task is simple too: the advised method is a subtask,
            // so the advice is completed after the method is completed too
            if (returnType == typeof(Task))
            {
                return(adviceTask);
            }

            // only Task<> left here
            // we need to create a new source and mark it as complete once the advice has completed
            var adviceTaskSource = TaskCompletionSource.Create(returnType.GetTaskType());

            adviceTask.ContinueWith(t => ContinueTask(t, adviceTaskSource, adviceValues));
            return(adviceTaskSource.Task);
        }