我设置了一个简单的类和拦截器(严重基于freezable示例),
using System;
using Castle.Core.Logging;
using System.Collections.Generic;
using System.Reflection;
using Castle.DynamicProxy;
[Serializable]
public class Pet
{
public virtual string Name { get; set; }
public virtual Dictionary<String, int> Dict { get; set; }
public Pet()
{
Dict = new Dictionary<string, int>();
}
public override string ToString()
{
return string.Format("Name: {0}, Age: {1}", Name, Dict);
}
public object getFieldDirect(string name)
{
return GetType().BaseType.GetField(
name,
BindingFlags.Instance | BindingFlags.NonPublic
).GetValue(this);
}
}
public class PetXample
{
public PetXample()
{
Console.WriteLine( new NullLogger() );
Pet rex;
rex = Something.MakeSomething<Pet>();
rex.Name = "Rex";
rex.Dict["key"] = 2;
rex.ToString();
Console.WriteLine( rex.ToString() );
}
}
public static class Something
{
private static readonly ProxyGenerator _generator = new ProxyGenerator(new PersistentProxyBuilder());
public static TSomething MakeSomething<TSomething>() where TSomething : class, new()
{
TSomething proxy = _generator.CreateClassProxy<TSomething>( new MyInterceptor() );
return proxy;
}
}
[Serializable]
public class MyInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
if( invocation.Method.Name.StartsWith("set_") )
{
string shortName = invocation.Method.Name.Substring(4);
string intName = "<" + shortName + ">k__BackingField";
object obj = invocation.InvocationTarget;
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
FieldInfo fi = invocation.TargetType.GetField(
intName,
flags
);
Console.WriteLine( shortName + ": " + fi.FieldType + " - " + fi.GetValue(obj) );
}
}
}
除了访问Pet
的内部词典键之外,其中我的工作方式完全正常。是否有任何方法可以自动拦截该访问权限(我假设没有),或者我最好只是限制访问私有权限而只允许通过功能访问?
答案 0 :(得分:1)
执行rex.Dict["key"] = 2;
与
Dictionary<String, Int32> dico = rex.Dict;
dico["key"] = 2;
如您所见,调用rex.Dict["key"] = 2;
不会在rex实例上调用任何set方法。你的拦截器不会拦截任何东西。
要实现您想要的目标,您还必须代理字典。
例如:
[Serializable]
public class Pet
{
public virtual String Name { get; set; }
public virtual IDictionary<String, Int32> Dict { get; set; }
public Pet()
{
this.Dict = Something.MakeSomething<IDictionary<String, Int32>>(new Dictionary<String, Int32>());
}
public override String ToString()
{
return String.Format("Name: {0}, Age: {1}", Name, Dict);
}
}
public static class Something
{
private static readonly ProxyGenerator _generator = new ProxyGenerator(new PersistentProxyBuilder());
public static TSomething MakeSomething<TSomething>() where TSomething : class, new()
{
TSomething proxy = _generator.CreateClassProxy<TSomething>(new MyInterceptor());
return proxy;
}
public static TSomething MakeSomething<TSomething>(TSomething instance) where TSomething : class
{
TSomething proxy = _generator.CreateInterfaceProxyWithTargetInterface<TSomething>(instance, new MyInterceptor());
return proxy;
}
}
[Serializable]
public class MyInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
if (invocation.Method.IsSpecialName && invocation.Method.Name.StartsWith("set_"))
{
PropertyInfo pi = invocation.TargetType.GetProperty(invocation.Method.Name.Substring(4), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
Console.WriteLine("{0}[{1}]({2})", pi.Name, pi.PropertyType, String.Join(" - ", invocation.Arguments.Select(a => a.ToString()).ToArray()));
}
}
}