【发布时间】:2020-01-09 03:22:31
【问题描述】:
序言/上下文
所以目前我有一个 Log 方法。
public T Log<T>(Func<T> func)
{
string methodName = func.Method.Name;
bool success = false;
T product = default(T);
Debug($"Entering {methodName}");
try
{
product = func.Invoke();
success = true;
}
catch (Exception e)
{
Info($"FAILURE: {methodName}: {e.Message}");
}
Debug($"{success.ToString().ToUpper()}: Exiting {methodName}");
return product;
}
这对我来说真的很管用,而且是这样称呼的
Log(() => AddTwoNumbers(1, 2));
我一直在使用装饰器模式,基本上说接口的所有方法都调用它们的基(或包含的对象,或者您想要实现基方法)以便记录方法。
免责声明 在我的情况下,我无法轻松访问 AOP,因此生成处理此问题的代理并非易事。我主要是对遗留代码进行大修,并从 Visual Basic 6 EXE 调用我的 .NET 库,据我所知,这些 AOP 框架中的大多数都需要直接合并到应用程序中。
我要解决的问题
很多时候我发现自己在这样做:
public int AddFirstFourNumbers(params int[] numbahs)
{
Log(() =>
{
int product;
product += numbahs[0];
product += numbahs[1];
product += numbahs[2];
product += numbahs[3];
return product;
}
}
或者像这样装饰扩展类的所有成员
public override int AddTwoNumbers(int num1, int num2)
{
return Log(() => base.AddTwoNumbers(num1, num2));
}
我想把它变成这样:
[Log]
public int AddFirstFourNumbers(params int[] numbahs)
{
int product;
product += numbahs[0];
product += numbahs[1];
product += numbahs[2];
product += numbahs[3];
return product;
}
还有这个
[Log]
public override int AddTwoNumbers(int num1, int num2)
{
return base.AddTwoNumbers(num1, num2);
}
我对创建自定义属性不是很熟悉,但是有没有办法将此日志属性修饰的方法视为委托并将其传递给第一个块中描述的 Log 方法?我在 Microsoft Docs 上看到的示例似乎没有做任何接近我希望的事情。
同时,我们拥有 MVC 验证属性,它似乎提供了大量有用的功能,所以这可能还可能。
我是 Action 和 Func Wrappers 的忠实粉丝,它们允许我装饰我的基本方法并分离出我的关注点。我只是在寻找一种更清洁的方法。如果能够将[WithImpersonation] 添加到方法的顶部或[UndoOnFailure] 并仅在实际方法块中显示核心实现,那就太好了。
【问题讨论】:
-
MVC 属性的工作方式是,框架中有代码查找这些属性并激活它们。你需要在这里做同样的事情,所以使用属性并不能真正给你带来太多好处。
-
是的,它看起来像。我可以[添加反射] (docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…),但随后我会在每个方法开始时调用 Log 和 Lambda-ing 我的方法主体来调用属性。这几乎是 AOP 提供的没有代码混乱的东西。
-
我正在写一个答案,你可以考虑一个替代方案。
-
嘿,我已经为这个(以及更广泛的)目的创建了这个库。如果您的应用程序至少与 netstandard2.0 兼容,您可以使用 2.x,否则使用 1.x 版本。 github.com/pamidur/aspect-injector
标签: c# reflection