相关疑难解决方法(0)

如何在C#中拦截方法调用?

对于给定的类,我希望有跟踪功能,即我想记录每个方法调用(方法签名和实际参数值)和每个方法退出(只是方法签名).

我如何做到这一点假设:

  • 我不想为C#使用任何第三方AOP库,
  • 我不想将重复的代码添加到我想要跟踪的所有方法中,
  • 我不想更改类的公共API - 类的用户应该能够以完全相同的方式调用所有方法.

为了使问题更具体,让我们假设有3个类:

 public class Caller 
 {
     public static void Call() 
     {
         Traced traced = new Traced();
         traced.Method1();
         traced.Method2(); 
     }
 }

 public class Traced 
 {
     public void Method1(String name, Int32 value) { }

     public void Method2(Object object) { }
 }

 public class Logger
 {
     public static void LogStart(MethodInfo method, Object[] parameterValues);

     public static void LogEnd(MethodInfo method);
 }
Run Code Online (Sandbox Code Playgroud)

如何调用Logger.LogStartLogger.LogEnd每次调用方法1方法2,而无需修改Caller.Call方法,没有明确地加入调用Traced.Method1Traced.Method2

编辑:如果我允许稍微更改Call方法,会有什么解决方案?

c# reflection aop

148
推荐指数
7
解决办法
8万
查看次数

有没有办法解决WPF除了反射之外调用GC.Collect(2)?

我最近不得不将这个怪物检入生产代码来操作WPF类中的私有字段:( tl; dr我如何避免这样做?)

private static class MemoryPressurePatcher
{
    private static Timer gcResetTimer;
    private static Stopwatch collectionTimer;
    private static Stopwatch allocationTimer;
    private static object lockObject;

    public static void Patch()
    {
        Type memoryPressureType = typeof(Duration).Assembly.GetType("MS.Internal.MemoryPressure");
        if (memoryPressureType != null)
        {
            collectionTimer = memoryPressureType.GetField("_collectionTimer", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as Stopwatch;
            allocationTimer = memoryPressureType.GetField("_allocationTimer", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as Stopwatch;
            lockObject = memoryPressureType.GetField("lockObj", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null);

            if (collectionTimer != null && allocationTimer != null && lockObject != null)
            {
                gcResetTimer = new Timer(ResetTimer);
                gcResetTimer.Change(TimeSpan.Zero, …
Run Code Online (Sandbox Code Playgroud)

c# reflection wpf garbage-collection

46
推荐指数
4
解决办法
2525
查看次数

通过使用格式错误的Json调用ASP.NET WebMethod来捕获错误

我们有一个较旧的ASP.NET WebForms应用程序,它通过$.ajax()在客户端使用jQuery 调用来执行AJAX请求,在使用[WebMethod]属性修饰的页面代码隐藏中调用静态方法.

如果在WebMethod中发生未处理的异常,则它不会触发Application_Error事件,因此我们的错误记录器(ELMAH)不会将其捕获.这是众所周知的而不是问题 - 我们将所有WebMethod代码包装在try-catch块中,并将异常手动记录到ELMAH.

但是,有一个案例令我难过.如果格式错误的Json发布到WebMethod URL,它会在输入我们的代码之前抛出异常,我找不到任何方法来捕获它.

例如,这个WebMethod签名

[WebMethod]
public static string LeWebMethod(string stringParam, int intParam)
Run Code Online (Sandbox Code Playgroud)

通常使用Json有效负载调用,如:

{"stringParam":"oh hai","intParam":37}
Run Code Online (Sandbox Code Playgroud)

我尝试使用Fiddler进行测试,将有效负载编辑为格式错误的Json:

{"stringParam":"oh hai","intPara
Run Code Online (Sandbox Code Playgroud)

ArgumentExceptionJavaScriptObjectDeserializer发送到客户端获得以下错误响应(这是在本地运行的简单测试应用程序,没有自定义错误):

{"Message":"Unterminated string passed in. (32): {\"stringParam\":\"oh hai\",\"intPara","StackTrace":"   at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeString()\r\n   at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeMemberName()\r\n   at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth)\r\n   at 
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n   at 
System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n   at 
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n   at 
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n   at 
System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)\r\n   at …
Run Code Online (Sandbox Code Playgroud)

asp.net ajax error-handling webmethod

16
推荐指数
1
解决办法
5286
查看次数

.NET任务的性能指标/诊断

有没有办法从.NET获取数据(C#5或更新,所以后异步/等待)执行等待执行的任务,以及类似的指标,用于诊断生产服务器发生的问题?

我正在讨论的案例是一个异步全能的系统(例如一个大规模并行套接字服务器,其中每个请求从一开始就是异步运行),其中初始任务产生多个任务,每个任务都需要时间来处理(或者每个启动更多任务),或者生成一些任务阻塞的任务(如第三方代码),其中一些正确地处理异步.我看到有两种情况难以有效诊断:

  • 在正常负载下,一切正常,但如果有足够的请求,那么CPU会很快跳到100%并且所有请求都会变得越来越慢.当负载减少时,CPU将保持100%,直到大多数待处理任务逐渐完成,然后CPU降至正常水平.
  • 在正常负载下,一切正常,但如果有足够的请求,那么某些请求(所有这些都是正确的异步)都不再完成或非常慢.当负载减少时,CPU将在处理完毕后保持100%,但任务完成率会出现速度颠簸,并且在短时间内会大幅减速.

我已经尝试为此编写一个简单的测试,但没有明显的方法来限制执行程序的数量和我需要创建的任务数量来测试它使解析信息变得非常困难.通过尝试注销调试信息也很难不干扰测试本身.我会继续尝试创建一个更好的测试用例,并在需要时修改我的问题.

根据我对问题和异步任务系统的理解,这两者实际上是对实际运行任务的执行程序的争用.

第一种情况发生是因为创建的任务比实际完成的更多,在这种情况下,即使在负载足够高以锁定服务之前,待处理任务的计数器也可用于诊断它.

第二种情况发生是因为一组任务足够长而不会随着时间的推移而产生(有足够的负载)所有执行程序最终同时运行这些任务.一旦完成,它将处理一些任务,但很快就会被另一个长期运行的任务所取代.在这种情况下,挂起的任务计数器将是有用的,以及一些其他指标.

有什么类型可用,或者是否有一些未记录/ hacky方法将一些代码移植到应用程序中启动的每个任务的开始/结束,以使其注销/测量这些内容并在任务编号时发出警告正在爆炸?

.net c# task async-await

10
推荐指数
1
解决办法
850
查看次数

Mono.Cecil可以修改已经加载在AppDomain中的代码吗?

我想在运行时向某个类添加一些行为.我知道如何在运行时使用Reflection.Emit进行子类化,但这还不够,根据一些外部配置,我需要在类型T上的方法中注入操作码,以便从中继承的所有类自动获得此行为.(我无法使用.NET分析API)

可以用Mono.Cecil完成这样的事吗?

如果不能修改加载的程序集上的代码,那很好.如果我可以在加载程序集之前进行修改然后将修改后的程序集加载到内存中,但我不知道如何控制程序集加载.

.net c# profiling intermediate-language mono.cecil

9
推荐指数
1
解决办法
2542
查看次数

Mono 中的运行时方法挂钩

我有一个现有的应用程序,它是闭源的,并且发布了自己的 Mono 3.5 版本。我想改变应用程序的行为;具体来说,我想用一个新的类替换一个内置类。

通常,使用Mono.Cecil 来解决这个问题。但是,在我的情况下,应用程序程序集是从只读卷加载的,这使得修改程序集本身非常棘手(它涉及硬件黑客来生成新卷)。但是,我可以通过官方支持的机制让它加载任意 DLL,理论上我可以使用它在运行时修改程序集。

有许多资源可用于通过 .NET Framework 实现运行时代码注入/函数挂钩,但在 Mono 下它们都失败了。我见过的方法包括:

查看相关问题:

我知道这是一个非常糟糕的计划。但是,由于我没有源代码,并且修改磁盘上的程序集甚至比进行某种肮脏的运行时 hack 还要糟糕,因此这是我迄今为止生成的最佳替代方案。

reflection mono jit code-injection

5
推荐指数
0
解决办法
1310
查看次数

如何在运行时替换方法实现?

我想拥有可以用我自己的自定义属性装饰的属性 getter 和方法,并根据该属性的存在用不同的实现替换方法主体。此外,不同的实现将需要知道赋予自定义属性的构造函数参数,它装饰方法。

这显然可以用 AOP 来完成,比如 PostSharp 或 LinFu,但我想知道是否有一种方法可以做到这一点,而不涉及构建后处理步骤,因为添加这比我更喜欢的项目复杂化。

.net c# aop dynamic-programming dynamic-proxy

4
推荐指数
1
解决办法
8673
查看次数

如何在我的方法的指针中替换指向重写(虚拟)方法的指针?(发布x64和x86)

问题 动态替换C#方法的内容? 我从@ Logman那里得到了很好的回应.我没有资格在评论中提出这个问题.

using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace ReplaceHandles
{
    class Program
    {
        static void Main(string[] args)
        {
            Injection.replace();
            Target target = new Target();
            target.test();
            Console.Read();
        }
    }

    public class Injection
    {
        public static void replace()
        {
            MethodInfo methodToReplace = typeof(Target).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
            MethodInfo methodToInject = typeof(Target2).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
            RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
            RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
            ReplaceInner(methodToReplace, methodToInject);
        }

        static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject)
        {
            unsafe
            {
                if (IntPtr.Size == 4) …
Run Code Online (Sandbox Code Playgroud)

c#

3
推荐指数
1
解决办法
1727
查看次数