Skip to content

Instantly share code, notes, and snippets.

@akimboyko
Created May 16, 2013 03:00
Show Gist options
  • Select an option

  • Save akimboyko/5589086 to your computer and use it in GitHub Desktop.

Select an option

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
// Multicast aspect to all properties of classes in namespace
[assembly: VirtualKeywordRequiredForInstanceProperties(
AttributeTargetTypes = "CodeSmells.FakeDataAccessLibrary.Entity.*",
AttributeTargetElements = MulticastTargets.Property)]
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; }
}
}
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