C#:如何在调用时触发事件的方法上创建属性?

2024-06-22

在 C# 或 .NET 中,是否有一种方法可以在方法上创建一个属性,以便在调用该方法时触发事件?理想情况下,我能够在调用该方法之前和之后运行自定义操作。

我的意思是这样的:

[TriggersMyCustomAction()]
public void DoSomeStuff()
{
}

我完全不知道如何做到这一点或者是否可能,但是系统.诊断.条件属性 http://msdn.microsoft.com/en-us/library/system.diagnostics.conditionalattribute.aspx可能会在后台做类似的事情。但我不确定。

EDIT:我忘了提及,由于我的具体情况,性能并不是真正的问题。


这个概念用于MVC http://en.wikipedia.org/wiki/ASP.NET_MVC_Framework网络应用程序。

The .NET框架4.x提供了几个触发操作的属性,例如:ExceptionFilterAttribute(处理异常),AuthorizeAttribute(处理授权)。两者都定义在System.Web.Http.Filters.

例如,您可以定义自己的授权属性,如下所示:

public class myAuthorizationAttribute : AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        // do any stuff here
        // it will be invoked when the decorated method is called
        if (CheckAuthorization(actionContext)) 
           return true; // authorized
        else
           return false; // not authorized
    }

}

然后,在你的控制器类,您装饰应该使用您的授权的方法,如下所示:

[myAuthorization]
public HttpResponseMessage Post(string id)
{
    // ... your code goes here
    response = new HttpResponseMessage(HttpStatusCode.OK); // return OK status
    return response;
}

每当Post方法被调用时,它会调用IsAuthorized里面的方法myAuthorization属性before里面的代码Post方法被执行。

如果你回来false in the IsAuthorized方法,您发出信号表示未授予授权并且该方法的执行Post aborts.


为了理解它是如何工作的,让我们看一个不同的例子:ExceptionFilter,它允许使用属性过滤异常,其用法与上面所示的类似AuthorizeAttribute(您可以找到有关其用法的更详细说明here https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling).

要使用它,请导出DivideByZeroExceptionFilter类来自ExceptionFilterAttribute如图所示here http://blog.karbyn.com/articles/handling-errors-in-web-api-using-exception-filters-and-exception-handlers/,并重写该方法OnException:

public class DivideByZeroExceptionFilter : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Exception is DivideByZeroException)
        {
            actionExecutedContext.Response = new HttpResponseMessage() { 
                Content = new StringContent("A DIV error occured within the application.",
                                System.Text.Encoding.UTF8, "text/plain"), 
                StatusCode = System.Net.HttpStatusCode.InternalServerError
                };
        }
    }
}

然后使用以下演示代码来触发它:

[DivideByZeroExceptionFilter]
public void Delete(int id)
{
    // Just for demonstration purpose, it
    // causes the DivideByZeroExceptionFilter attribute to be triggered:
    throw new DivideByZeroException(); 

    // (normally, you would have some code here that might throw 
    // this exception if something goes wrong, and you want to make
    // sure it aborts properly in this case)
}

现在我们知道了它是如何使用的,我们主要对实现感兴趣。以下代码来自 .NET Framework。它使用接口IExceptionFilter内部作为合同:

namespace System.Web.Http.Filters
{
    public interface IExceptionFilter : IFilter
    {
        // Executes an asynchronous exception filter.
        // Returns: An asynchronous exception filter.
        Task ExecuteExceptionFilterAsync(
                    HttpActionExecutedContext actionExecutedContext, 
                    CancellationToken cancellationToken);
    }
}

The ExceptionFilterAttribute其本身定义如下:

namespace System.Web.Http.Filters
{
    // Represents the attributes for the exception filter.
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, 
            Inherited = true, AllowMultiple = true)]
    public abstract class ExceptionFilterAttribute : FilterAttribute, 
            IExceptionFilter, IFilter
    {
        // Raises the exception event.
        // actionExecutedContext: The context for the action.
        public virtual void OnException(
            HttpActionExecutedContext actionExecutedContext)
        {
        }
        // Asynchronously executes the exception filter.
        // Returns: The result of the execution.
        Task IExceptionFilter.ExecuteExceptionFilterAsync(
            HttpActionExecutedContext actionExecutedContext, 
            CancellationToken cancellationToken)
        {
            if (actionExecutedContext == null)
            {
                throw Error.ArgumentNull("actionExecutedContext");
            }
            this.OnException(actionExecutedContext);
            return TaskHelpers.Completed();
        }
    }
}

Inside ExecuteExceptionFilterAsync, 方法OnException叫做。由于您已如之前所示覆盖了它,因此现在可以通过您自己的代码来处理该错误。


正如 OwenP 的回答中提到的,还有一种商业产品可用,后锐利 http://www.postsharp.net/,这可以让您轻松做到这一点。Here http://doc.postsharp.net/method-interception#intercepting-method是一个如何使用 PostSharp 做到这一点的示例。请注意,有一个 Express 版本可供您免费使用,甚至可以用于商业项目。

PostSharp 示例(请参阅上面的链接以获取完整说明):

public class CustomerService
{
    [RetryOnException(MaxRetries = 5)]
    public void Save(Customer customer)
    {
        // Database or web-service call.
    }
}

这里该属性指定Save如果发生异常,该方法最多被调用 5 次。以下代码定义了此自定义属性:

[PSerializable]
public class RetryOnExceptionAttribute : MethodInterceptionAspect
{
    public RetryOnExceptionAttribute()
    {
        this.MaxRetries = 3;
    }

    public int MaxRetries { get; set; }

    public override void OnInvoke(MethodInterceptionArgs args)
    {
        int retriesCounter = 0;

        while (true)
        {
            try
            {
                args.Proceed();
                return;
            }
            catch (Exception e)
            {
                retriesCounter++;
                if (retriesCounter > this.MaxRetries) throw;

                Console.WriteLine(
                  "Exception during attempt {0} of calling method {1}.{2}: {3}",
                  retriesCounter, args.Method.DeclaringType, args.Method.Name, e.Message);
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#:如何在调用时触发事件的方法上创建属性? 的相关文章

  • 在子目录中构建共享库

    我正在尝试构建一个使用一些 C 代码的 R 包 我有一个编译为可执行文件的 C 库 可以从命令行调用 有一个与之关联的 Makefile 我正在尝试获取信息here http cran r project org doc manuals R
  • 使用索引避免迭代器失效,维护干净的接口

    我创建了一个MemoryManager
  • 在宏中使用 # [重复]

    这个问题在这里已经有答案了 请解释一下代码 include
  • 指向指针的指针和指向二维数组的指针之间的区别

    如果我有一个二维数组 B 定义为 int B 2 3 1 3 5 2 4 6 Is int p B与 一样int p 3 B int f B printf d f 1 gives 5作为输出 同时printf d f 给出 1 作为答案 为
  • 多态性中基类缺少虚拟析构函数 = 资源泄漏?

    我们知道 如果要多态地使用基类 则需要将基类的析构函数指定为 virtual 否则程序中可能会出现资源泄漏 因为只会调用基类析构函数 而不会调用派生对象析构函数 我们还知道构造函数 析构函数纯粹是初始化 未初始化构造 而operator n
  • 将标准库添加到C++ eclipse项目中

    一个 非常 新手 C 问题 有没有办法自动将标准库添加到 C eclipse 项目中 我安装了 CDT 主要功能插件 您可以手动添加 STL 标头的路径路径和符号 gt 包含选项卡 http help eclipse org galileo
  • 如何在 C++ 中从模板基类的构造函数调用模板超类的构造函数?

    我正在使用 sublimetext3 用 c 进行编程 我的程序有一个名为 Array 的超类和一个名为 IntArray 的子类 这两个类都是模板类 目前 我在编译该程序时遇到问题 它不断在我的 IntArray cpp 文件中给出错误
  • 命令中带空格的 Windows C 系统调用

    我无法使用名称和参数中的空格进行系统调用 例如 system c program files something example exe c my files example txt 我尝试过各种我知道的方法来逃避 但没有任何效果 我努力了
  • 测试从 ComboBox 派生的自定义控件

    我创建了一个从 ComboBox 派生的控件 并希望对其行为进行单元测试 但是 它在我的单元测试中的行为似乎与实际应用程序中的行为不同 在实际应用程序中 Combobox DataSource 属性和 Items 同步 换句话说 当我更改
  • Linux C++ 调试器

    我正在寻找完美的 Linux C 调试器 我不期望成功 但搜索应该提供丰富的信息 我是一个非常有能力的 gdb 用户 但 STL 和 Boost 很容易压垮我的调试技能 并不是说我无法深入了解数据结构的内部结构 而是它需要很长时间 我通常会
  • ASP.NET 中的 thread.sleep

    我正在为我的网站模拟彗星实时馈送协议 因此在我的控制器中我添加 while nothing new before timeout Thread Sleep 1000 但我注意到添加此功能后整个网站变慢了 调试后我得出结论 当我打电话时Thr
  • OpenMP 循环数组访问中的错误共享

    我想利用 OpenMP 来并行执行我的任务 我需要将数组的所有元素减去相同的数量并将结果写入另一个向量中 两个数组都是动态分配的malloc第一个填充了文件中的值 每个元素都有类型uint64 t pragma omp parallel f
  • 链接错误:xxx 已在 *****.LIB 中定义:: 究竟出了什么问题?

    Problem 我正在尝试使用一个名为DCMTK http dicom offis de dcmtk它使用了一些其他外部库 zlib libtiff libpng libxml2 libiconv 我已经从同一网站下载了这些外部库 LIB
  • 如何从另一个线程阻止 UI 线程或强制表单在 UI 线程内运行

    我的应用程序的一个要求是 如果它失去数据库连接 那么它必须弹出一个大模式 无连接 稍后重试 对话框 阻止所有用户交互 直到重新获得连接为止 我通过在应用程序启动时启动 DeviceMonitor 类的实例来实现此目的 该类创建一个 Syst
  • 没有类型的 IEnumerable 属性

    我正在尝试创建一个类似于来自 MSDN 的官方 DataGrid ItemsSource 的属性 public IEnumerable ItemsSource get set 这提供了对任何派生类中任何类型的支持 有了这个 我可以设置类似的
  • 矩阵行列式算法 C++

    我是编程新手 我一直在寻找一种找到矩阵行列式的方法 我在网上找到了这段代码 但我很难理解这里的算法 我对递归的基础没有问题 但继续和主循环我很难理解 非常感谢任何可以向我解释该算法的人 int determ int a MAX MAX in
  • PC 上 XNA 中的信箱和缩放

    有没有一种方法可以让我基本上以 1080p 或 720p 作为默认分辨率来开发 XNA 游戏 然后根据设置的分辨率将游戏中的所有内容缩放到适当的大小 而不必在每个 Sprite 中设置缩放因子Draw 方法 我的想法是 我可以基于 1080
  • 如何以一对一/零关系更新员工和身份用户

    我正在尝试更新员工记录 也想更新身份用户 如果我先单独更新身份用户 例如 UserManager Update user Context Entry employee State System Data Entity EntityState
  • 如何从与 C# lambda 集成(而非代理集成)的 Amazon API 网关获取正确的 http 状态代码?

    我正在使用 C lambda 与 API 网关集成 我希望 API 网关返回正确的错误代码 例如 400 404 500 等 API网关模块tf文件 provider aws version lt 2 70 0 region var aws
  • RC4 实现与 openssl 输出不匹配

    我的目标是在 C C 中实现 RC4 流密码 并确保它产生与使用时相同的输出openssl命令 按照伪代码维基百科 https en wikipedia org wiki RC4 该实现似乎有效 因为它可以加密和解密内容 但是 加密的输出与

随机推荐

  • C# 中的文件名匹配问题

    我之前发布过类似的内容 但它是关于处理命令提示符的 与另一个实例一样 我尝试在 ERP 系统中的备份之前进行一些自动文件清理 我对其执行维护 以平滑流程 因为我对其中 6 个系统至少执行两次维护 每一个月 所以 这里有一些正在发生的事情的例
  • Django-allauth 注册、登录和社交连接集成到一页中

    如何使用 django allauth 将社交登录 登录表单和注册表单加载到索引页面 类似于您访问 facebook com 时的情况 帐户 网址已经可以使用 我尝试复制
  • JSON 解析 C# 模型

    我似乎无法解析一些 json 以将其转换为模型 JSON status ok count 100 data nickname God id null account id 1000076613 nickname god0 id null a
  • 为什么 sed 不将 \t 识别为制表符?

    sed s t 1 filename gt sedTmpFile mv sedTmpFile filename 我期待这个sed脚本插入一个tab在每一行前面 filename然而事实并非如此 由于某种原因 它正在插入一个t反而 Not a
  • 使用 pythonwhois 测试域名可用性

    我使用成功pythonwhois 安装有pip install 检查 com 域的可用性 import pythonwhois for domain in aaa com bbb com details pythonwhois get wh
  • 如何在 R 中使用 glm 循环多次曝光和结果以及不同模型?

    下面的代码当前针对每个结果的每次曝光 每个结果 3 次曝光 运行未经调整的 glm 并将结果导出到列表中 对于每次曝光 我需要 3 个模型 model 1 未调整 我们目前有 model 2 针对 cov1 进行调整 model 3 针对
  • 矢量可绘制图像视图上的洪水填充算法

    我想创建这样的应用程序 洪水填充算法 https stackoverflow com q 9748206 4535930 我应用了该代码 它可以很好地处理 JPG 或 PNG 文件 但我想将该算法与 Vector 可绘制图像视图一起使用 V
  • 第二次运行程序返回 EADDRINUSE 进行绑定 [重复]

    这个问题在这里已经有答案了 可能的重复 进程退出时释放绑定端口 https stackoverflow com questions 548879 releasing bound ports on process exit Windows 和
  • Facebook API:无法在 Android 上登录

    我正在尝试使用 Facebook API 在 Android 上实现 Facebook 登录 我已经按照方法做了一切Facebook 登录流程 http developers facebook com docs android login
  • 如何在 VB.NET 中对数组进行 JSON 编码?

    我需要为我正在使用的例程传回 JSON 结果 在VB NET 数组如何进行JSON编码 Dim serializer as New JavaScriptSerializer Dim arrayJson as String serialize
  • 在 Holoviews/Datashader 中更改分类数据的颜色图

    我正在尝试使用 Datashader 和 Holoviews 可视化分类空间数据 类似于https anaconda org jbednar census hv dask notebook https anaconda org jbedna
  • Rails 5 form_for 与复选框数组

    我使用的是 PostgreSQL 数据库和 Rails 5 0 6 我尝试为我工作的学校构建一个课程分配 WebApp 对于每门课程 教师都可以选择允许访问该课程的形式 迁移文件 def up create table courses do
  • 基于布尔值的淡入/淡出

    我想知道我是否真的必须写 if status status image id fadeIn else status image id fadeOut 或者有一个函数可以提供我的布尔状态 例如 status image id fade sta
  • UIView ClipsToBounds 属性:它会提高性能吗?

    文档说clipsToBounds的财产UIView会将绘图剪裁到边界 或更准确地说subView不能在范围之外绘制superView 听起来不错 但这在实践中意味着什么 如果我将其设置为YES 那么我的subView将自动只绘制不在边界之外
  • jstl 中的多个项目的迭代

    我需要在 jstl 中同时迭代 3 个列表 为了迭代单个列表 我们使用
  • jQuery 1.4.x 和 @ 符号

    我曾经使用这个脚本进行 jquery 电子邮件混淆 replaceAt replaceWith obfuscate each function this attr href mailto this text a class obfuscat
  • 如何在xamarin.android中将dp转换为px?

    我想将 dp 转换为 pxC code in xamarin android 但我能找到的只是java代码在 android studio 中xamarin 有一些问题 我尝试使用等效项 例如使用 Resources 而不是 getReso
  • C++包含整个C语言吗? [复制]

    这个问题在这里已经有答案了 我在教程中读到 C 包含整个 C 编程语言 不过我也读过 在一些地方像这样 https stackoverflow com questions 598552 should i learn c before lea
  • Symfony 框架 - 将西里尔文数据从装置加载到数据库中

    如何将包含西里尔文数据的夹具文件中的数据加载到数据库中 我已经尝试过了 但是数据库中的数据被转换为 符号 我的装置文件以 UTF 8 编码保存 你使用 MySQL 吗 您可能需要更改数据库中表的排序规则和 或字符集 A 整个部分都存在于 M
  • C#:如何在调用时触发事件的方法上创建属性?

    在 C 或 NET 中 是否有一种方法可以在方法上创建一个属性 以便在调用该方法时触发事件 理想情况下 我能够在调用该方法之前和之后运行自定义操作 我的意思是这样的 TriggersMyCustomAction public void Do