I have two questions that are related to Contracts and AOP using PostSharp:
The built-in support for Code contracts that worked well with Visual Studio 2015 seems to have ended starting with Visual Studio 2017 (unfortunately in my opinion). So I'm not looking to use the Contracts from MS with PostSharp (unless that's possible using VS 2017)?
1.) So as an alternative, I was thinking whether it was possible to use the Contracts provided by PostSharp, and use it in conjunction with AOP?
I had previously been using PostSharp's AOP support in order to "inject" logging across my application as a way to clear the code of cross-cutting concerns, and that went really well I thought. I would like to add Contracts to my code in a similar manner if possible?
I can see that it's possible to add contracts like so:
public class CustomerModel
{
public void SetFullName([Required] string firstName, [Required] string lastName)
{
this.FullName = firstName + " " + lastName;
}
}
But to retroactively add "[Required]" to every relevant method in the entire code base feels like a drag :)
It seems that there’s no way to use PostSharp's AOP in conjunction with Contracts? Perhaps this is by design, since I can imagine that it’d be very hard to take into account all the various possibilities of different method signatures that existed. But nonetheless, I just wanted to make sure there wasn’t a "magic" way that made it possible, e.g. using AOP to automatically add a Contract.Requires(args != null) (but I understand that it’s hard to accomplish since you can’t apply the same contract to primitive data types etc.).
2.) Second question is that I couldn’t fnd an equivalent to Contract.Ensures(Contract.Result() != null) or something like that?
1) To apply the PostSharp code contract aspect to multiple target elements at once you can employ aspect provider combined with attribute multicasting. For example:
[PSerializable]
public class RequiredProviderAttribute : MethodLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
MethodBase targetMethod = (MethodBase) targetElement;
ObjectConstruction contract = new ObjectConstruction(typeof(RequiredAttribute));
foreach (var parameterInfo in targetMethod.GetParameters())
{
yield return new AspectInstance(parameterInfo, contract);
}
}
}
[RequiredProvider(AttributeTargetMemberAttributes = MulticastAttributes.Public)]
public class Program
{
static void Main(string[] args)
{
Method1(null);
}
private static void Method1(object a)
{
Method2(a);
}
// Contract is applied to the parameter of this method
public static void Method2(object a)
{
}
}
2) PostSharp code contracts currently support only custom attributes syntax. To check the post-conditions you can however apply these custom attributes to the ref and out parameters and to the method return values. You can also implemented your own custom code contracts.