3

I've come across an interesting problem, probably as a result of the design of a 3rd party API I have no control over.

Consider the following example code:

class MyClass : ThirdPartyClass {
    void SpecialFunction() {
        //...
    }
}

The 3rd party API calls SpecialFunction after internal processing.

I can add an attribute to tell the API that it should be called prior to internal processing:

[DoFirst]
void SpecialFunction() { ... }

However this means that I have to have two additional classes if I want to run the same function before and after the API's internal processing:

class MyClass : ThirdPartyClass {
    public void DoSpecialFunction() { ... }
}

class MyClassPre : ThirdPartyClass {
    MyClass myClass;
    [DoFirst]
    void SpecialFunction() {
        myClass.DoSpecialFunction();
    }
}

class MyClassPost : ThirdPartyClass {
    MyClass myClass;
    void SpecialFunction() {
        myClass.DoSpecialFunction();
    }
}

This is obviously not valid:

class MyClass : ThirdPartyClass {
    [DoFirst]
    void SpecialFunction() { _SpecialFunction(); }

    void SpecialFunction() { _SpecialFunction(); }

    void _SpecialFunction() { ... }
}

Is there perhaps some C# way I can manipulate the attributes, or the function signatures, so that additional classes aren't required?

Perhaps via some way of extension? (SpecialFunction is not an override)

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Danzapps
  • 101
  • 4
  • How to you want to call the `MyClass.SpecialFunction()` method from another class !? – Behzad Jun 19 '15 at 05:35
  • There's nothing in C# that would let you have two method with the same name. If there's a way to do it; it would totally depend on the implementation of your API. – shf301 Jun 19 '15 at 05:36
  • How about having 2 methods in myClass to control the calling behavior. Where in first method, SpecialFunction() is called after internal processing and the opposite in second method. – Yogi Jun 19 '15 at 05:36
  • See http://stackoverflow.com/questions/2160476/how-to-set-attributes-values-using-reflection – Benj Jun 19 '15 at 05:36
  • @BehzadKhosravifar - I was probably too terse in my example. ``ThirdPartyClass`` has a full lifecycle which calls methods you can optionally define. The startup functions of ``MyClassPre`` and ``MyClassPost`` would retrieve ``MyClass`` for use in ``SpecialFunction()``. – Danzapps Jun 19 '15 at 05:40
  • What you could do is: Create the two classes A1, A2 you already mentioned and an additional third class B. you could wrap one object A1 and one object A2 in B, update them both and specify in B which one contains valid data ... and discard the other one – Benj Jun 19 '15 at 05:40
  • @Yogi - Unfortunately the function name is crucial. If the method is not called ``SpecialFunction()`` the third party API will not call it. – Danzapps Jun 19 '15 at 05:41

1 Answers1

4

As mentioned in the comments, you cannot have two methods with the same name and arguments that differ only by their decorated attributes.

Presumably the Third Party API is using reflection to identify the SpecialFunction() and so you should be able to simplify your workaround as follows:

// An instance of this class will Do After
public class MyClass : ThirdPartyClass 
{
    public virtual void SpecialFunction() 
    { 
       // All the work goes here
    }
}

// An instance of this class will Do First
public class MyClassPre : MyClass 
{
    [DoFirst]
    public override void SpecialFunction() 
    {
        base.SpecialFunction();
    }
}

If the third party API is provided to you by an organisation with which you are partnered or from whom you are consuming services, you may be able to request that they add a [DoAfter] attribute that triggers the default behaviour as well. In which case you could simply decorate as follows:

class MyClass : ThirdPartyClass 
{
    [DoFirst]
    [DoAfter]
    void SpecialFunction()
    {
        //  ...
    }
}
Steve Lillis
  • 3,263
  • 5
  • 22
  • 41
  • Thanks for your response! Your suggestion does get me closer to a more user friendly result. I still feel like it should be better for end users, but it's now clear to me that this is purely down to the API I'm working with. I'll see if I can suggest an additional attribute to make things a bit more logical. – Danzapps Jun 19 '15 at 09:12