Robert Waite
Robert Waite

Reputation: 271

Can you call a method on a different Customization package?

We have an initiative where we need to have communication between two distinct customization packages. So we have customization A that needs to invoke a method that is best suited to be implemented in Customization B. My thoughts to date are to set up a WebHook then invoke the function we need by directly engaging the webhook from customization A. Before I proceed with implementing this, I wanted to reach out to see how others have solved this requirement. Is it possible to call functions from other customizations directly in C# I have not come across any reference on being able to do so, therefore, I assume it’s not possible? But wanted to reach out and ask first.

Thanks in advance!

Robert

Upvotes: 1

Views: 132

Answers (2)

1- Use an interface to locate/implement the code to call. I prefer interface methods instead of static methods for multiple reasons but the main reasons are:

a) They can be overridden or easily delegated to another implementation.

b) You can be sure that you are dealing with the right method.

c) For static methods, you have to know the class it is in before hand. For implemented methods, you don't care what is the class the method is declared in. Many static methods can have the same signature but do different things since they are not tied to a known interface.

d) You can add the interface as a simple dll shared in a separate customization (with you other interfaces).

e) You don't pollute your other interfaces as it is separate.

f) You announce what you do but not how you do it.

g) Interfaces are the best way to maintain well decoupled constructs.

h) They are ideal when using the Strategy Pattern

public interface ISomeInterface {
    object DoSomething(); 
}


OR

public interface ISomeInterface, PXGraph, new() {
    object DoSomething(); 
}

2- Implement your interface as many times as you want in as many customization packages as you want as such. Your implementations do not need to be a PXGraph but they can if you wish to share code with it or access other shared pieces of code.

public class SomeGraph : PXGraph<SomeGraph>, ISomeInterface {

       public object DoSomething() {
          do something;
          return result;
       }
}

3- Then, in some parts of any loaded code, find your implementations and call them. In my case, I have used the Post-publish interface:

public class B2BFramework : CustomizationPlugin {

    public override void UpdateDatabase() {
        var impls = B2BUtils.GetImplementations<IDataFactory>();
        foreach (var impl in impls) {
            var dataFactory = (IDataFactory)Activator.CreateInstance(impl);
            var result = factory.DoSomething();
        }
    }
}

4- Here is the code for B2BUtils.GetImplementations();

    public static IEnumerable<Type> GetImplementations<T>() {
        return GetImplementations(typeof(T));
    }

    public static IEnumerable<Type> GetImplementations(Type interfaceType) {
        var impls = new List<Type>();
        foreach (var ass in AppDomain.CurrentDomain.GetAssemblies()) {
            if (PXSubstManager.IsSuitableTypeExportAssembly(ass, true)) {
                Type[] types = null;
                try {
                    if (!ass.IsDynamic)
                        types = ass.GetExportedTypes();
                } catch (ReflectionTypeLoadException te) {
                    PXTrace.WriteError("An exception occured when loading assembly {0}: {1}", ass.FullName, te.Message);
                    types = te.Types;
                } catch (Exception ex) {
                    PXTrace.WriteError("An exception occured when loading assembly {0}: {1}", ass.FullName, ex.Message);
                    continue;
                }
                if (types != null) {
                    foreach (var t in types) {
                        if (interfaceType.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract) {
                            impls.Add(t);
                        }
                    }
                }
            }
        }
        return impls;
    }

Upvotes: 2

Gabriel
Gabriel

Reputation: 3783

Are you talking about invoking a static function included in a different customization, or calling an actual instance method that is in another graph extensions?

Both options are possible -- all your customizations end up getting compiled and published to the same folder (App_RuntimeCode and the bin folders if you have any DLLs), and you can safely access code contained in a different customization project.

If you want to call an instance method of another graph extension, you will first need to retrieve an instance of the graph extension where it is available:

var someExtension = Base.GetExtension<SomeExtension>();
someExtension?.SomeFunction();

Upvotes: 1

Related Questions