9 Replies Latest reply on Jan 20, 2012 7:43 AM by MvanderVeeken

    static AFDatareference.GetValue(...

    Zev.Arnold@Wipro

      I'm trying to determine the fewest number of methods I need to override in my custom AF DataReference.  I was wondering if anybody could give me an idea of what applications might call the static GetValue method.  This method takes an AFAttributeList, context, and a time context and returns an AFValues that contains one AFValue for each AFAttribute in the AFAttributeList.

       

      If I don't overload this method for my custom Data Reference, what are the ramifications?

       

      Thanks,
      Zev

        • Re: static AFDatareference.GetValue(...
          mhamel

          PI Notifications, PI Web Parts and PI OLEDB Enterprise are both using GetValue and GetValues, PI ProcessBook is using almost all the time the GetValues. Those are the ones I know. Any future application developed on top of PI AF will also require both. PI System Explorer (PSE) is using the GetValue method often to display the result inside the right pane. If you intend to use a Data Reference in your project to solve real-life problem, you should foresee to implement both GetValue and GetValues methods. The ramifications of not implementing the GetValue method depends on the PI System related application. If in the purpose of your project it does not make sense to return a single value, you will have to implement the SupportedMethods and do not return the AFDataReferenceMethod.GetValue value. By doing such, some applications relying on the GetValue would certainly throw an exception.

           

          The minimal required ones in a practical way are:

           

           

           
          ' Methods            
              Public Function GetValue(ByVal context As Object, ByVal timeContext As Object, ByVal inputAttributes As AFAttributeList, ByVal inputValues As AFValues) As AFValue        
              Public Function GetInputs(ByVal context As Object) As AFAttributeList
               
          ' Properties    
              Public Property ConfigString As String        
              Public ReadOnly Property SupportedContexts As AFDataReferenceContext
              Public ReadOnly Property SupportedMethods As AFDataReferenceMethod
          
           
          

           For a complete list of overridable members, consult this list below.

           
           
          ' Methods    
              Public Sub CreateConfig()
              Public Function GetInputs(ByVal context As Object) As AFAttributeList
              Public Function GetValue(ByVal context As Object, ByVal timeContext As Object, ByVal inputAttributes As AFAttributeList, ByVal inputValues As AFValues) As AFValue
              Public Function GetValues(ByVal context As Object, ByVal timeContext As AFTimeRange, ByVal numberOfValues As Integer, ByVal inputAttributes As AFAttributeList, ByVal inputValues As AFValues()) As AFValues
              Public Sub SetValue(ByVal context As Object, ByVal newValue As AFValue)
              
          ' Properties
              Public Property Attribute As AFAttribute
              Public Property ConfigString As String    
              Public ReadOnly Property EditorType As Type
              Public ReadOnly Property IsConfigured As Boolean    
              Public ReadOnly Property ServerTime As AFTime
              Public ReadOnly Property ServerTimeZone As AFTimeZone
              Public ReadOnly Property Span As Double
              Public ReadOnly Property [Step] As Boolean
              Public ReadOnly Property SupportedContexts As AFDataReferenceContext
              Public ReadOnly Property SupportedMethods As AFDataReferenceMethod
              Public Property Template As AFAttributeTemplate
              Public Property UOM As UOM
              Public ReadOnly Property ValueEditorType As Type
              Public ReadOnly Property Zero As Double
          
           
          

           Let me know if that answered your question.

           

           

            • Re: static AFDatareference.GetValue(...
              Zev.Arnold@Wipro

              Mathieu,

               

              Thank you for your speedy and detailed response.  My question really only pertained to the static version of the GetValue method.  I fully intend to override the instance versions of the GetValue function.

               

              I noticed that your post excluded the static version of the GetValue method from your list of overridable members.  On review of the PI AFSDK Reference, I noted that this function is not virtual (of course, since it's static).  My mistake...

               

              -Zev

                • Re: static AFDatareference.GetValue(...
                  mhamel

                  The static GetValue method has a different role. The prototype looks like this:

                   

                  Public Shared Function GetValue(ByVal attributes As AFAttributeList, _

                   

                                                  ByVal context As Object, _

                   

                                                  ByVal timeContext As Object) As AFValues

                   

                      Return Nothing

                   

                  End Function

                   

                   

                  Or in C#

                   

                   

                   

                  public static AFValues GetValue(AFAttributeList attributes, object context,

                   

                                                  object timeContext)

                   

                  {

                   

                      return null;

                   

                  }

                   

                   

                  This shared method is intended gets the value for multiple attributes based upon the data reference configuration within the specified context. The attributes argument represents the list of attributes to obtain a value from. The returned collection of AFValues will be specified in the same order as the list of attributes provided.

                   

                   

                   

                  This static GetValue method is declared as a static member of an inheritable class (AFDataReference) and get be “override” in a certain extent. In fact, it consists of hiding the base class static method in the derived class. This method provides a mechanism to read multiple attribute values in one call, giving the data reference an opportunity to provide for faster performance than if retrieved by individual calls. Because this method is static, it must be overridden using the new keyword in C#, or Shadows in VB.NET. If this method is not provided in the Data Reference implementation, then the SDK will invoke the GetValue call for each attribute.

                   

                   

                   

                  In VB.NET it gives:

                   

                   

                   

                   

                   

                  Public Shared Shadows Function GetValue(ByVal attributes As AFAttributeList, _

                   

                                                          ByVal context As Object, _

                   

                                                          ByVal timeContext As Object) _

                   

                                                          As AFValues

                   

                      'Implement your logic here.

                   

                  End Function

                   

                   

                   

                  Public Shadows Function GetValue(ByVal context As Object, _

                   

                                                   ByVal timeContext As Object, _

                   

                                                   ByVal inputAttribute As AFAttributeList, _

                   

                                                   ByVal inputValues As AFValues) _

                   

                                                   As AFValue

                   

                      'Implement your logic here.

                   

                  End Function                                                   

                   

                   

                  Or in C#:

                   

                   

                   

                  public new static AFValues GetValue(AFAttributeList attributes, object context,

                   

                                                      object timeContext)

                   

                  {

                   

                      //Implement your logic here.

                   

                  }

                   

                   

                   

                  public override AFValue GetValue(object context, object timeContextArg,

                   

                                                   AFAttributeList inputAttributes, AFValues inputValues)

                   

                  {

                   

                      //Implement your logic here.

                   

                  }

                   

                   

                  If you do not implement your version of this shared method, the SDK will invoke the GetValue call for each attribute. Does it answer your question better?

                    • Re: static AFDatareference.GetValue(...
                      Zev.Arnold@Wipro

                      Huh.  That's interesting.  Does the SDK use Reflection to determine whether or not our custom Data Reference has implemented a static GetValue method?  If not, how does it call it?  In what situations might this be called?  

                        • Re: static AFDatareference.GetValue(...
                          mhamel

                          Zev, you are right the reflection principle is used to determine if a static GetValue method is provided in your custom data reference. If none is implemented, a default internal implementation will call the individual GetValue method per attribute. This is normally slower than going through the static GetValue method. This is normally used when you invoke the GetValue method of an AFAttributeList object.

                            • Re: static AFDatareference.GetValue(...
                              Zev.Arnold@Wipro

                              Thanks Mathieu for that neat "under-the-covers" look!

                               

                              Is this actually used in any of the client applications you mentioned above or is it strictly included for custom development?

                                • Re: static AFDatareference.GetValue(...
                                  mhamel

                                  For example, this faster method of getting values for multiple attributes in an AFAttributeList is implemented in the PI Point Data Reference. I have not seen this implementation in any of the other official OSIsoft AF Data Reference (Table Lookup, Formula). I have not seen a use of it in client applications for now, but I am convinced the time where this feature will be leveraged is not so far.

                                   

                                  Probably, a member of the SDK team could chime in and complete my answer.

                                    • Re: static AFDatareference.GetValue(...
                                      cmanhard

                                      First, one correction - in order for this method to be called, you must set the "MultipleAttributes" flag in the DR's SupportedMethods property.

                                       

                                      AF Client applications indirectly call this through AFAttributeList.GetValue.  Actually, even a simple call to a single attribute, like a Formula Data Refrence, can result in AFAttributeList.GetValue being called for the Formula's inputs.  While Formula and Table Lookup do not implement the multiple GetValue function, they do implement the "GetInputs" function, which allows the AFSDK to pre-fetch this data in this optimal way. AFSDK evaluates the full list of inputs prior to retrieving data so to cause as few round-trips to the PI Server as possible.

                              • Re: static AFDatareference.GetValue(...
                                MvanderVeeken

                                Some added information/clarification on Mathieu's post, because this is a tricky subject and comes down to some OOP principles.

                                 

                                For this explanation I'm using C# keywords as an example, the same applies to VB.NET using corresponding keywords.

                                 

                                In C# you can create virtual methods, these can be overriden in derived classes using the override keyword. When you override an existing (virtual) method, you are creating a new implementation of a method with the same signature. 

                                 

                                .NET does not support virtual static methods. Why not? It does not make any sense. Say I would have a static HelperClass.HelpMethod(). Why would I want some random derived class' method implementation to be called. This is not logical. If you have a base class HelperClass and some derived class called HelperDerivedClass you would just call either HelperClass.HelpMethod() or HelperDerivedClass.HelperMethod.

                                 

                                If you want to achieve something like this, you can use the Singleton pattern or a (normal) class hierarchy with the Factory pattern or Dependancy injection pattern. This way you can achieve different behavior in different parts of your application.

                                 

                                In this case, AFDataReference has a static method called 'GetValue'. It cannot be virtual, so it cannot be overridden in a derived class. What happens if you derive from AFDataReference and want to implement your own version of this static GetValue method? You cannot use the override keyword, and you don't have to. You can just implement the method. This will automatically hide the base class implementation of the static GetValue method. Well, why would you need the new keyword in this case? The compiler will complain with the following warning:

                                 

                                warning CS0108: ''AFDerivedDataReference.GetValue() hides inherited member 'AFDataReference.GetValue(). Use the new keyword if hiding was intended.

                                 

                                This is exactly as we discussed above. Our derived implementation of the static GetValue() method hides the static GetValue() method of the base class. Why is the compiler complaining about the new keyword then? It is only for documentation purposes! Using the new keyword will only suppress this warning, it does not make the methods behave differently. Why are you 'forced' to use it? The C# compiler is just friendly, and wants to make sure you are doing something you explicitly intend to do.

                                 

                                The following includes some assumptions, maybe the AF Developers (Chris Manhard) are at liberty to confirm or elaborate on this.

                                 

                                If AF needs to use the static GetValue() method, it will find out the type of the current DataReference using Reflection. It will then call this static GetValue method (with the right signature) and retrieve the output. This object will always derive from AFDataReference. If no implementation of this static GetValue() method exists in the derived class, the AFDataReference.GetValue() method will be used (basic OOP). If there is an implementation (either with or without the new keyword) than that implementation is called.