[英]Is there a generic way to call another method whenever a method is called in C#
[英]Call a method whenever a property is called
有没有办法向类添加一个属性或类似的东西,每当调用该类的属性时,将调用一个方法?
基本上我有包含数据行的类,而不是像以下那样访问单个列:(DataRow [“some_column_name”])我想使用属性来访问它们,如:(MyClass.some_column_name)。
我目前的工作是使用反射动态传递列名作为参数,如下所示:
public string some_column_name
{
get
{
return (string)GetValue(MethodBase.GetCurrentMethod().Name);
}
set
{
SetValue(MethodBase.GetCurrentMethod().Name, value);
}
}
上面提到的方法的问题是,如果我有一个包含10个属性的类,那么所有这些属性都将在其中使用上面的代码片段。
下面的代码示例包含上面代码片段的get和set value方法,这些方法将在基类中:
private DataRow some_table;
protected object GetValue(string columnName)
{
return some_table[columnName.Substring(columnName.IndexOf('_') + 1)];
}
protected object SetValue(string columnName, object value)
{
return some_table[columnName.Substring(columnName.IndexOf('_') + 1)] = value;
}
您可以使用[CallerMemberName]
属性。 如果用这个属性装饰方法参数,如下所示:
protected object GetValue([CallerMemberName] string columnName = null)
{
return some_table[columnName.Substring(columnName.IndexOf('_') + 1)];
}
protected object SetValue(object value, [CallerMemberName] string columnName = null)
{
return some_table[columnName.Substring(columnName.IndexOf('_') + 1)] = value;
}
编译器将使用调用者成员(方法)名称而不是默认空值。 所以你的财产变成了:
public string some_column_name
{
get
{
// current method name ("some_column_name") will be passed
// as "column" parameter
return (string)GetValue();
}
set
{
// same here
SetValue(value);
}
}
另一种替代方法可能是从DynamicObject
继承:
public class DynamicRow : DynamicObject {
public override bool TryGetMember(GetMemberBinder binder, out object result) {
// this will be called when you access dynamic property
// like x.some_column_name
result = GetValue(binder.Name);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
// this will be called when you assign dynamic property
// like x.some_column_name = "some value"
SetValue(binder.Name, value);
return true;
}
private DataRow some_table;
protected object GetValue(string columnName) {
return some_table[columnName.Substring(columnName.IndexOf('_') + 1)];
}
protected object SetValue(string columnName, object value) {
return some_table[columnName.Substring(columnName.IndexOf('_') + 1)] = value;
}
}
然后你可以像这样使用它:
dynamic x = new DynamicRow();
object val = x.some_column_name;
x.some_column_name = "some value";
但我个人并不喜欢它,因为与使用第一种方法中的静态属性列表相比,您正在失去所有类型的安全性(任何拼写错误只会在运行时捕获)。
以下是使用PostSharp AOP
的代码的简单工作版本。 这里的结果将是TestProperty ,因为我们修剪了get_
和set_
。 在OnInvoke
可以进行更多处理,可以使用MethodInterceptionArgs
对调用者进行大量修改,然后我们可以选择从PostSharp调用本身返回或进一步执行该方法。 您还可以计划使用OnMethodBoundaryAspect
等AOP函数,它可以在方法成功或失败时执行
namespace TestAOP
{
class Program
{
static void Main(string[] args)
{
var t = new Test();
var x = t.TestProperty;
Console.WriteLine(x);
Console.Read();
}
}
public class Test
{
private string _test = "InitialValue";
[CustomProperty]
public string TestProperty
{
get => _test;
set => _test = value;
}
}
[Serializable]
public sealed class CustomPropertyAttribute : MethodInterceptionAspect
{
public override void OnInvoke(MethodInterceptionArgs args)
{
args.ReturnValue = args.Method.Name.Substring(args.Method.Name.IndexOf("_", StringComparison.Ordinal) + 1);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.