如何像python一样在c#中编写函数装饰器

Roc*_*Gom 7 c# .net-4.5

我已经在 python 上工作了一段时间,然后回到 c# 进行了一个项目。所以我习惯了 python 语言,这迫使我像 python 程序员一样思考,我喜欢这个!

我想问的问题是如何创建一个在其 decarator 之后调用的方法?

Python 装饰器语法:

def p_decorate(func):
   def func_wrapper(name):
       return "<p>{0}</p>".format(func(name))
   return func_wrapper

@p_decorate
def get_text(name):
   return "lorem ipsum, {0} dolor sit amet".format(name)
Run Code Online (Sandbox Code Playgroud)

我用谷歌搜索但只找到了 .Net Attributes它对我没有帮助。

示例代码,但我想编写自己的 AuthorizationAttribute 类。

public class RestrictAccessToAssignedManagers : AuthorizationAttribute
{
    protected override AuthorizationResult IsAuthorized(System.Security.Principal.IPrincipal principal, AuthorizationContext authorizationContext)
    {
        EmployeePayHistory eph = (EmployeePayHistory)authorizationContext.Instance;
        Employee selectedEmployee;
        Employee authenticatedUser;

        using (AdventureWorksEntities context = new AdventureWorksEntities())
        {
            selectedEmployee = context.Employees.SingleOrDefault(e => e.EmployeeID == eph.EmployeeID);
            authenticatedUser = context.Employees.SingleOrDefault(e => e.LoginID == principal.Identity.Name);
        }

        if (selectedEmployee.ManagerID == authenticatedUser.EmployeeID)
        {
            return AuthorizationResult.Allowed;
        }
        else
        {
            return new AuthorizationResult("Only the authenticated manager for the employee can add a new record.");
        }
    }
}

[RestrictAccessToAssignedManagers]
public void InsertEmployeePayHistory(EmployeePayHistory employeePayHistory)
{
    if ((employeePayHistory.EntityState != EntityState.Detached))
    {
        this.ObjectContext.ObjectStateManager.ChangeObjectState(employeePayHistory, EntityState.Added);
    }
    else
    {
        this.ObjectContext.EmployeePayHistories.AddObject(employeePayHistory);
    }
}
Run Code Online (Sandbox Code Playgroud)

来自MSDN 的示例代码

Sco*_*ain 6

这通常用在面向方面的编程中,两个流行的库是PostSharpFody

这是原始 python 示例的 PostSharp 示例。

using System;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Extensibility;

namespace SandboxConsole
{
    class Program
    {

        static void Main(string[] args)
        {
            Console.WriteLine(GetText("Test"));
            Console.ReadLine();
        }

        [Decorate]
        public static string GetText(string name)
        {
            return String.Format("lorem ipsum, {0} dolor sit amet", name);
        }
    }

    [Serializable]
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class DecorateAttribute : MethodInterceptionAspect
    {
        public override bool CompileTimeValidate(MethodBase method)
        {
            if (!((MethodInfo)method).ReturnType.IsAssignableFrom(typeof(string)))
            {
                Message.Write(SeverityType.Error, "CUSTOM01", "Can not apply [Decorate] to method {0} because it does not retun a type that is assignable from string.", method);
                return false;
            }
            return true;
        }

        public override void OnInvoke(MethodInterceptionArgs args)
        {
            args.Proceed();
            args.ReturnValue = String.Format("<p>{0}</p>", args.ReturnValue);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)