2013-11-28 12 views
5

के साथ ContextBoundObject मेरे पास एक प्रणाली है जो ContextBoundObject के साथ AOP का उपयोग करती है।Astec/Await

इसका उपयोग विधि कॉल को रोकने और फ़ंक्शन के पहले और बाद में कुछ संचालन करने के लिए किया जाता है। यह तब तक ठीक काम करता है जब तक कि मैं 'फ़ंक्शन को अवरुद्ध नहीं किया जाता' async।

मैं समझता हूँ कि सी # संकलक जैसे ही 'का इंतजार है' तो यह अवरोधन में जारी है पहुँच जाता है एक राज्य मशीन है, जो सिंक करने के लिए नियंत्रण रिटर्न में async तरीकों का पुनर्लेखन और कोड जो केवल क्रियान्वित किया जा करने के लिए है कार्यान्वित विधि के बाद।

मैं देख सकता हूं कि IMessageSink में "AsyncProcessMessage" है, लेकिन मुझे इसे आमंत्रित करने का कोई तरीका नहीं मिल रहा है, और मुझे यकीन नहीं है कि यह async/प्रतीक्षा परिदृश्य में काम करेगा या नहीं।

क्या Async/Await ContextBoundObject के साथ काम करने का कोई तरीका है? क्या एक और पहलू ओरिएंटेड प्रोग्रामिंग का उपयोग यहां एकमात्र विकल्प है?

नीचे दिए गए कोड नमूने में 'ऑडिट' विशेषता के साथ सजाए गए तरीके को ऑडिट किया गया है और ऑडिटफैक्ड में रखा गया है जो एक ContextBoundObject है। ऑडिट सिंक में सिंकप्रोसेस मैसेज विधि में विधि से पहले और बाद में निष्पादित किया जाना तर्क है।

[AuditBoundary] 
public class AuditFacade : ContextBoundObject 
{ 
    [Audit] 
    public ResponseObject DoSomthing() 
    { 
     //Do something 
     return new ResponseObject(); 
    } 

    /// <summary> 
    /// Async Method to be intercepted 
    /// </summary> 
    /// <returns></returns> 
    [Audit] 
    public async Task<ResponseObject> DoSomthingAysnc() 
    { 
     //Do something Async 
     await Task.Delay(10000); 
     return new ResponseObject(); 
    } 
} 

[AttributeUsage(AttributeTargets.Method)] 
public class AuditAttribute : Attribute 
{ 
} 

[AttributeUsage(AttributeTargets.Class)] 
public class AuditBoundaryAttribute : ContextAttribute 
{ 
    public AuditBoundaryAttribute() 
     : base("AuditBoundary" + Guid.NewGuid().ToString()) 
    { 
    } 
    public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg) 
    { 
     ctorMsg.ContextProperties.Add(new AuditProperty()); 
    } 
} 

public class AuditProperty : IContextProperty, IContributeObjectSink 
{ 
    public string Name 
    { 
     get { return "AuditProperty"; } 
    } 

    public bool IsNewContextOK(Context newCtx) 
    { 
     var p = newCtx.GetProperty("AuditProperty") as AuditProperty; 

     if (p == null) 
      return false; 

     return true; 
    } 

    public void Freeze(Context newContext) 
    { 
    } 

    public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink) 
    { 
     return new AuditSink(nextSink); 
    } 

} 

public class AuditSink : IMessageSink 
{ 
    private IMessageSink nextSink; 

    public AuditSink(IMessageSink nextSink) 
    { 
     this.nextSink = nextSink; 
    } 

    public IMessage SyncProcessMessage(IMessage msg) 
    { 
     var message = msg as IMethodCallMessage; 

     IMethodReturnMessage returnMessage = null; 
     ResponseObject response; 

     //Some Pre Processing happens here 
     var newMessage = new MethodCallMessageWrapper(message); 

     //Invoke the Method to be Audited 
     returnMessage = nextSink.SyncProcessMessage(newMessage) as IMethodReturnMessage; 
     response = returnMessage.ReturnValue as ResponseObject; 

     //Some Post Processing happens here with the "response" 
     return returnMessage; 
    } 

    public IMessageSink NextSink 
    { 
     get { return this.nextSink; } 
    } 
    public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) 
    { 
     return nextSink.AsyncProcessMessage(msg, replySink); 
    } 
} 

उत्तर

0

मैं ContextBoundObject बारे में कुछ पता नहीं है, लेकिन मुझे लगता है कि AsyncProcessMessage() साथ async लेना देना नहीं है कि - await और निम्न सामान्य SyncProcessMessage() का उपयोग कर काम करना चाहिए:

  1. अपने preprocessing कदम करो ।
  2. async विधि को आमंत्रित करें।
  3. ContinueWith() या await का उपयोग करके, Task पर निरंतरता के रूप में अपना पोस्टप्रोसेसिंग चरण जोड़ें।
  4. कॉलर को निरंतरता Task पर लौटें।

यदि आप थ्रेड पूल पर अपने पोस्टप्रोसेसिंग निष्पादन के साथ ठीक हैं, तो ContinueWith() शायद आसान है। यदि आपको मूल संदर्भ पर निष्पादित करने के लिए पोस्टप्रोसेसिंग की आवश्यकता है, तो await का उपयोग करें।

await संस्करण इस दिखाई देगा:

var responseTask = (Task<ResponseObject>)returnMessage.ReturnValue; 

Func<Task<ResponseObject>> postProcessTaskFunc = async() => 
{ 
    var response = await responseTask; 
    // Some Post Processing happens here with the "response" 
    return response; 
} 

return new ReturnMessage(postProcessTaskFunc(), …); 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^