c# - 如何在上下文绑定(bind)对象中链接消息接收器(面向方面​​的编程)

标签 c# .net aop

我正在尝试使用 ContextBoundObject 和消息接收器将某些方面注入(inject)我的代码。

我的问题是我的方面只被调用一次 - 当我打电话时:myFacadee.GetValue("Tie") 我希望看到我的缓存方面被调用两次

  1. 一次用于“GetValue”方法
  2. 其次是在内部调用的“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/

相关文章:

c# - FTP错误227进入被动模式

c# - 如何调试 .NET Windows 服务 OnStart 方法?

java - java中对象作用域方法的静态实现

java - 如何在maven项目中使用AspectJ进行日志记录?

c# - 类型或命名空间名称不存在? (静态类)

c# - 永久服务 "Starting"状态

c# - 如何绕过 Microsoft.Bcl.Build 警告

c# - 如何唤醒 C# 中休眠的线程?

.net - 使用几个构造函数参数创建一个Quartz.NET Job

silverlight - 在Silverlight中拦截ViewModel