我怎么能阻止使用某些特定的类?

时间:2015-03-12 13:13:47

标签: c# restriction

我想自动化一些测试来检查程序员编写高效算法的能力。在此示例中,算法将在int数组中执行简单的二进制搜索。

public class ComplexityPractice
{
    public bool BinarySearch(int [] sortedArray, int value)
    {
        // to be implement 
    }
}

注意:此代码由受限域中的反射加载。

实现此方法的简单方法当然是来自.NET库的Array.BinarySearch(sortedArray, value)。但我的目标是检查程序员自己生成代码的能力,所以问题是:

如何阻止程序员使用Array类中的函数?

2 个答案:

答案 0 :(得分:-1)

方法1:

检查代码是否有效,然后测试它是否包含不允许的方法调用,但是您必须忽略字符串文字。
但是,如果Reflection可用,则不会阻止用户按名称调用方法。

bool validCode = true;
string[] unallowedMethods = new string[] 
{
  "Array.BinarySearch",
  ...
};
string sourceCode = ...;
ICodeCompiler codeCompiler = ...;
CompilerResults results = codeCompiler.CompileAssemblyFromSource(parameters, sourceCode);
validCode = result.Errors.Count == 0;
if (validCode)
 foreach (method in unallowedMethods)
   if (sourceCode.Contains(method)))
   //improve this by checking if occurrence is not a string literal in program 
   {
      validCode = false;
      break;
   }

方法2:

测试一个方法是否使用Mono Cecil调用另一个方法:
Take a look at this answer

static class MethodDefinitionExtensions
{
    public static bool CallsMethod(this MethodDefinition caller, 
        MethodDefinition callee)
    {
        return caller.Body.Instructions.Any(x => 
            x.OpCode == OpCodes.Call && x.Operand == callee);
    }
}

class Program
{
    private static AssemblyDefinition _assembly = AssemblyDefinition.ReadAssembly(
        System.Reflection.Assembly.GetExecutingAssembly().Location);

    private static void Method1()
    {
        Method2();
    }

    private static void Method2()
    {
        Method1();
        Method3();
    }

    private static void Method3()
    {
        Method1();
    }

    private static IEnumerable<MethodDefinition> GetMethodsCalled(
        MethodDefinition caller)
    {
        return caller.Body.Instructions
            .Where(x => x.OpCode == OpCodes.Call)
            .Select(x => (MethodDefinition)x.Operand);
    }

    private static MethodDefinition GetMethod(string name)
    {
        TypeDefinition programType = _assembly.MainModule.Types
            .FirstOrDefault(x => x.Name == "Program");
        return programType.Methods.First(x => x.Name == name);
    }

    public static void Main(string[] args)
    {
        MethodDefinition method1 = GetMethod("Method1");
        MethodDefinition method2 = GetMethod("Method2");
        MethodDefinition method3 = GetMethod("Method3");

        Debug.Assert(method1.CallsMethod(method3) == false);
        Debug.Assert(method1.CallsMethod(method2) == true);
        Debug.Assert(method3.CallsMethod(method1) == true);

        Debug.Assert(GetMethodsCalled(method2).SequenceEqual(
            new List<MethodDefinition> { method1, method3 }));
    }
}

答案 1 :(得分:-1)

我会考虑使用面向方面编程。

具体来说,我会结帐PostSharp

PostSharp提供方法边界,允许您在输入方法之前取消方法的执行。

以下是一个例子:

•OnEntry - 在执行方法体之前

•OnExit - 即使出现错误

,也始终在方法执行时调用

•OnSuccess - 仅在方法执行完毕且没有异常时调用

•OnException - 仅在方法由于未处理的异常而停止执行时调用

http://www.postsharp.net/blog/post/Day-4-OnMethodBoundaryAspect