我正在尝试使用 ContextBoundObject
和消息接收器将某些方面注入(inject)我的代码。
我的问题是我的方面只被调用一次 -
当我打电话时:myFacadee.GetValue("Tie")
我希望看到我的缓存方面被调用两次
- 一次用于“
GetValue
”方法 - 其次是在内部调用的“
GetValues
” 'GetValue
' 方法
但是,它仅在第一次“GetValue
”方法调用时被调用一次。
如何更改/修复以下代码以确保我的“MyFacade
”对象上的所有方法都导致调用缓存方面。即使它们被同一“MyFacde
”对象中的其他方法调用?
这是我的代码的简化示例:
测试应用:
class Program
{
static void Main(string[] args)
{
var myFacadee = new MyFacade();
System.Console.WriteLine("Value:\t" + myFacadee.GetValue("Tie"));
System.Console.ReadLine();
}
}
门面:
[Cache]
public class MyFacade : ContextBoundObject
{
public string GetValue(string name)
{
return GetValues().FirstOrDefault(x => x.EndsWith(name));
}
public List<string> GetValues()
{
return new List<string>
{
"You asked for a Shirt",
"You asked for a Pants",
"You asked for a Tie"
};
}
}
缓存属性:
[AttributeUsage(AttributeTargets.Class)]
public class CacheAttribute : ContextAttribute
{
public CacheAttribute() : base("Security") { }
public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
ctorMsg.ContextProperties.Add(new CacheProperty());
}
}
缓存属性:
public class CacheProperty : IContextProperty, IContributeObjectSink
{
public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
{
return new CacheAspect(next);
}
public void Freeze(Context newContext)
{
// no op
}
public bool IsNewContextOK(Context ctx)
{
var newContextLogProperty = ctx.GetProperty("CacheProperty") as CacheProperty;
if (newContextLogProperty == null)
{
Debug.Assert(false);
return false;
}
return (true);
}
public string Name { get { return "CacheProperty"; } }
}
缓存方面:
internal class CacheAspect : IMessageSink
{
internal CacheAspect(IMessageSink next)
{
_next = next;
}
private readonly IMessageSink _next;
public IMessageSink NextSink
{
get { return _next; }
}
public IMessage SyncProcessMessage(IMessage msg)
{
Preprocess(msg);
var returnMethod = _next.SyncProcessMessage(msg);
return returnMethod;
}
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
throw new InvalidOperationException();
}
private void Preprocess(IMessage msg)
{
// We only want to process method calls
if (!(msg is IMethodMessage)) return;
var call = msg as IMethodMessage;
var type = Type.GetType(call.TypeName);
var callStr = type.Name + "." + call.MethodName;
var argsString = call.Args.Aggregate((current, next) => current + ", " + next);
Console.WriteLine("Try to get value form cache : {0} for {1}({2})", callStr, call.MethodName, argsString);
}
}
最佳答案
它只被调用一次,因为上下文边界只被跨越一次。从实例内部调用同一实例不需要任何编码到上下文中,因此您的接收器不用于拦截消息。
关于c# - 如何在上下文绑定(bind)对象中链接消息接收器(面向方面的编程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7420035/