Created
May 16, 2013 03:00
-
-
Save akimboyko/5589086 to your computer and use it in GitHub Desktop.
Custom Architecture Constraints using PostSharp. Check that all properties of classes in namespace are: public, virtual, with both getter and setter. Based upon example from book "AOP in .Net" by @mgroves
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Multicast aspect to all properties of classes in namespace | |
| [assembly: VirtualKeywordRequiredForInstanceProperties( | |
| AttributeTargetTypes = "CodeSmells.FakeDataAccessLibrary.Entity.*", | |
| AttributeTargetElements = MulticastTargets.Property)] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace CodeSmells.FakeDataAccessLibrary.Entity | |
| { | |
| public class Customer | |
| { | |
| // This property is defined as expected | |
| public virtual int Id { get; set; } | |
| // without `virtual` keyword PostSharp will generate compile-time error message | |
| // otherwise NHiberante will generate exception during run-time | |
| public /*virtual*/ string Name { get; set; } | |
| // Both getter/setter are required to be public | |
| internal virtual string Description { get; private set; } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Linq; | |
| using System.Reflection; | |
| using PostSharp; | |
| using PostSharp.Constraints; | |
| using PostSharp.Extensibility; | |
| namespace CodeSmells.FakeDataAccessLibrary.Aspect | |
| { | |
| [Serializable] | |
| [MulticastAttributeUsage(MulticastTargets.Property)] | |
| public class VirtualKeywordRequiredForInstancePropertiesAttribute : ScalarConstraint | |
| { | |
| // Validation happens only at post-compile phase | |
| public override void ValidateCode(object target) | |
| { | |
| var propertyInfo = (PropertyInfo)target; | |
| var targetType = propertyInfo.DeclaringType; | |
| if (targetType != null) | |
| { | |
| var virtualInstanceProperty = targetType | |
| .GetProperties(BindingFlags.Public | BindingFlags.Instance) | |
| .Where(propInfo => propInfo.CanRead & propertyInfo.CanWrite) | |
| .Where(propInfo => propInfo.GetGetMethod() != null) | |
| .Where(propInfo => propInfo.GetGetMethod().IsVirtual) | |
| .Where(propInfo => propInfo.GetSetMethod() != null) | |
| .Where(propInfo => propInfo.GetSetMethod().IsVirtual) | |
| .SingleOrDefault(propInfo => propInfo == propertyInfo); | |
| if (virtualInstanceProperty == null) | |
| { | |
| Message.Write(MessageLocation.Of(targetType), | |
| SeverityType.Error, | |
| "998", | |
| "Property '{0}' in Entity class {1} show be public, virtual with both getter and setter", | |
| propertyInfo.Name, targetType.FullName); | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment