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

我试图使用ContextBoundObject和消息接收器将一些方面注入我的代码.

我的问题是我的方面只被调用一次 –
    当我打电话时:myFacadee.GetValue(“领带”)
    我希望看到我的缓存方面被调用两次

>一次用于’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"
                   };
    }
}

CacheAttribute:

[AttributeUsage(AttributeTargets.Class)]
public class CacheAttribute : ContextAttribute
{
    public CacheAttribute() : base("Security") { }

    public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
    {
        ctorMsg.ContextProperties.Add(new CacheProperty());
    }
}

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"; } }
}

CacheAspect:

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);
    }
}

最佳答案 它只被调用一次因为上下文边界只被交叉一次.从实例中调用同一实例不需要任何编组到上下文中,因此您的接收器不用于拦截消息.

点赞