using PostSharp.Aspects; using PostSharp.Extensibility; using PostSharp.Reflection; using PostSharp.Serialization; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace PostSharp.Samples.Encryption { [PSerializable] [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] public abstract class FilterAttribute : Attribute, IAspectProvider { public IEnumerable<AspectInstance> ProvideAspects(object targetElement) { var parameter = targetElement as ParameterInfo; if (parameter != null) { // When the attribute is applied on a parameter, we have to apply the filter when the method is invoked. var method = (MethodBase) parameter.Member; // Add an aspect to the method. Make sure we have a single aspect instance even if many parameters need filtering. var filterMethodArgumentsAspect = GetAspect<FilterMethodArgumentsAspect>(method); if (filterMethodArgumentsAspect == null) { filterMethodArgumentsAspect = new FilterMethodArgumentsAspect(method); yield return new AspectInstance(method, filterMethodArgumentsAspect); } filterMethodArgumentsAspect.SetFilter(parameter, this); } else { // When the attribute is applied on a field or property, we will apply the filter when asked implicitly. var locationInfo = LocationInfo.ToLocationInfo(targetElement); if (locationInfo.IsStatic) { Message.Write(locationInfo, SeverityType.Error, "MY02", "Cannot apply [{0}] to {1} because it is static.", GetType().Name, locationInfo); yield break; } var type = locationInfo.DeclaringType; if (type.IsValueType) { Message.Write(locationInfo, SeverityType.Error, "MY03", "Cannot apply [{0}] to {1} because the declaring type is a struct.", GetType().Name, locationInfo); yield break; } var filterTypePropertiesAspect = GetAspect<FilterTypePropertiesAspect>(type); if (filterTypePropertiesAspect == null) { filterTypePropertiesAspect = new FilterTypePropertiesAspect(); yield return new AspectInstance(type, filterTypePropertiesAspect); } filterTypePropertiesAspect.SetFilter(locationInfo, this); } } public abstract object ApplyFilter(object value); private static T GetAspect<T>(object target) { return PostSharpEnvironment.CurrentProject.GetService<IAspectRepositoryService>() .GetAspectInstances(target) .Select(aspectInstance => aspectInstance.Aspect) .OfType<T>() .SingleOrDefault(); } } }