如果您可以将属性设置为虚拟的,您就可以使用Castle Dynamic Proxy的拦截器。拦截器包含在调用给定方法时执行的行为。在这种情况下,我们将ModifyStringMethod应用于字符串属性的返回值。
如何实现:
1)添加对NuGet包Castle.Core的引用。
2)定义您的拦截器。
public class ModifyStringMethodInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
if (invocation.Method.Name.StartsWith("get_") &&
invocation.Method.ReturnType == typeof(string))
{
invocation.ReturnValue =
ModifyStringMethod((string)invocation.ReturnValue);
}
}
private static string ModifyStringMethod(string input)
{
return (input ?? "") + "MODIFIED";
}
}
上面的示例有一个Intercept方法,当您的属性被调用时会调用该方法。在示例中,您可以看到invocation.Proceed(),这将继续调用属性。
然后它检查是否为get_属性并返回一个字符串。
if (invocation.Method.Name.StartsWith("get_") &&
invocation.Method.ReturnType == typeof(string))
然后修改该方法的返回值。
invocation.ReturnValue = ModifyStringMethod((string)invocation.ReturnValue)
3)使用虚方法定义您希望添加此行为的对象(请注意,我也可以在此处使用自动实现属性)奖励
public class Intercepted
{
public virtual string A { get; set; }
}
4) 接下来使用DynamicProxy中的ProxyGenerator类创建对象实例,
例如:
public class Program
{
static void Main(string[] args)
{
var pg = new ProxyGenerator();
var intercepted = pg.CreateClassProxy<Intercepted>(new ModifyStringMethodInterceptor());
intercepted.A = "Set ... ";
Console.WriteLine(intercepted.A);
Console.ReadLine();
}
}
输出结果为:
Set ... MODIFIED
这里的好处是您的对象是“干净”的,例如它们不需要知道ModifyStringMethodInterceptor并且可以包含自动实现的属性,如果您有大量这些对象,则将大大减少代码量。
更进一步,如果您需要进一步控制,可以通过向类添加属性来应用此行为。
[AttributeUsage(AttributeTargets.Method)]
public class ModifyStringMethodAttribute : Attribute
{
}
然后定义对象为:
public class Intercepted
{
public virtual string A { [ModifyStringMethod] get; set; }
}
并且拦截器的修改:
if (invocation.Method.ReturnType == typeof(string) &&
invocation.Method.GetCustomAttributes(true)
.OfType<ModifyStringMethodAttribute>().Any())
{
invocation.ReturnValue =
ModifyStringMethod((string)invocation.ReturnValue);
}
检查属性,然后应用方法调用。
GetPropertyValue(string propertyName)
。 - ste-fuMyClass
具有读/写属性,而MyClassFacade
具有只读属性,用于公开修改后的MyClass
属性以供显示。 - Dan J