我想在我的代码中为每个具有特定类型参数的方法添加一个Contract.Requires。我怎么做到这一点?
考虑以下简单的例子:
public class ValuesController : ApiController
{
public string Get(int id)
{
return GetValue(id);
}
private string GetValue(int id)
{
Contract.Requires(HttpContext.Current.Request.Headers["key"] != null);
return id.ToString();
}
}
我怎样才能将其更改为:
public class ValuesController : ApiController
{
public string Get(int id)
{
return GetValue(id);
}
[AddContract]
private string GetValue(int id)
{
return id.ToString();
}
}
然后我可以在其中多播AddContract属性。
我考虑使用PostSharp,但似乎没有用。我认为这可能与PostSharp的IL编织没有很好地处理代码契约创建的元数据有关,但我的知识缺乏该领域。
我的尝试看起来像这样:
public class ValuesController : ApiController
{
public string Get(int id)
{
return GetValue(id);
}
[AddContract]
private string GetValue(int id)
{
return id.ToString();
}
}
[Serializable]
public class AddContract : MethodInterceptionAspect
{
public override void OnInvoke(MethodInterceptionArgs args)
{
Contract.Requires(HttpContext.Current.Request.Headers["key"] != null);
args.Proceed();
}
}
但是没有用 - 静态代码分析无法识别合同。
答案 0 :(得分:1)
PostSharp的方法是编译时编织,这意味着修改MSIL代码。为了使System.Diagnostics.Contracts能够很好地工作,PostSharp必须在代码合同之后运行。
好消息是您可以使用Code Contracts和PostSharp。 糟糕的是你不能将代码合同与PostSharp一起使用。
在这种情况下,我建议使用装饰模式来解决交叉问题:
interface IValuesController
{
string Get(int id);
}
public class ValuesController : IValuesController
{
public string Get(int id)
{
return id.ToString();
}
}
public class ValuesControllerWithContracts : IValuesController{
private IValuesController classToDecorate;
ValuesControllerWithContracts(IValuesController classToDecorate){
this.classToDecorate = classToDecorate;
}
public string Get(int id)
{
//decorate get property with contracts
Contract.Requires(HttpContext.Current.Request.Headers["key"] != null);
return classToDecorate.Get(id);
}
}
//constrution and usage, this work like a charm with Dependecy Inyection container or Factory Patterns
IValuesController valuesController = new ValuesController();
IValuesController valuesControllerWithContracts = new ValuesControllerWithContracts(valuesController)
valuesControllerWithContracts.Get(1);
答案 1 :(得分:0)
AddContract类未定义为属性
[Serializable]
public class AddContractAttribute : MethodInterceptionAspect
{