Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to shim/override members of facade #3

Closed
IFYates opened this issue Mar 22, 2021 · 3 comments · Fixed by #7
Closed

Allow to shim/override members of facade #3

IFYates opened this issue Mar 22, 2021 · 3 comments · Fixed by #7
Assignees

Comments

@IFYates
Copy link
Owner

IFYates commented Mar 22, 2021

Is your feature request related to a problem? Please describe.
Some interface facades can define members that don't exist in the shimmed member. While this can be useful, it would be powerful to be able to shim new functionality in for that member.
Additionally, being able to replace the functionality of the target using the same/similar mechanism.

Describe the solution you'd like
A way to decorate the interface member so that another type can handle the instance call.
Will need to be able to call the original implementation, rather than the shim proxy.

To differentiate and prevent unexpected issues at run-time, allow to choose that will "always override" or "never override", in case an added member is implemented by the target type

Describe alternatives you've considered
Standard extension methods are useful but only allow for extending with new members.

Example
Target:

public class TestClass {
    public void MethodA() { }
    public void MethodB() { }
}
public interface ITestClassFacade {
    void MethodA(); // Calls TestClass.MethodA, as default
    void MethodB(); // Will be overridden to call new implementation which will call the base implementation
    void MethodC(); // Provides new member implementation
}

Proxy implementation example:

public class TestClassProxy {
    readonly TextClass _inst;
    public TestClassProxy(TextClass inst) { _inst = inst; }

    public void MethodA() => _inst.MethodA();

    public void MethodB() {
        // pre-logic
        _inst.MethodB();
        // post-logic
    }

    public void MethodC() {
        // new logic
    }
}
@IFYates
Copy link
Owner Author

IFYates commented Mar 22, 2021

Goal: keep all decoration in the interface

Potential syntax:
ShimProxyAttribute(Type implementingType, enum(AddIfMissing, MustBeMissing, MustOverride) behaviour)

public interface ITestClassFacade {
    void MethodA();
    [ShimProxy(typeof(TestProxy), ProxyBehaviour.MustOverride)]
    void MethodB(); // Will be overridden to call new implementation which will call the base implementation
    [ShimProxy(typeof(TestProxy), ProxyBehaviour.MustBeMissing)]
    void MethodC(); // Provides new member implementation
}

public static class TestProxy {
    public static void MethodB(ITestClassFacade inst) {
        // pre-logic
        inst.MethodB(); // does not recurse as "inst" is underlying
        // post-logic
    }
    public static void MethodC(ITestClassFacade inst) {
        // new logic
    }
}

@IFYates
Copy link
Owner Author

IFYates commented Mar 23, 2021

Note that milestone v1.5.0 supports implemented interfaces, so some amount of additional code is possible.

Example:

public interface ITestClassFacade {
    void MethodA();
    [ShimProxy(typeof(TestProxy), ProxyBehaviour.MustOverride)]
    void MethodB(); // Will be overridden to call new implementation which will call the base implementation

    public void MethodC() {
        // new logic using "this"
    }
}

@IFYates IFYates self-assigned this Mar 29, 2021
IFYates pushed a commit that referenced this issue Mar 30, 2021
@IFYates
Copy link
Owner Author

IFYates commented Mar 30, 2021

Suggested implementation supports:

  • Add new method/property/field
  • "Override" method/property/field implementation
  • Alias of source method/property/field (if override)
  • Alias of implementation method/property/field
  • Overridden method implementation calling to underlying (not possible with property/field)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant