您可以在不同的自定义包上调用方法吗?

Can you call a method on a different Customization package?

我们有一个计划,我们需要在两个不同的定制包之间进行通信。所以我们有定制 A 需要调用最适合在定制 B 中实现的方法。我迄今为止的想法是设置一个 WebHook,然后通过直接从定制 A 中使用 Webhook 来调用我们需要的功能。在我继续之前通过实施这个,我想看看其他人是如何解决这个要求的。是否可以直接在 C# 中从其他自定义调用函数我没有遇到任何关于能够这样做的参考,因此,我认为这是不可能的?不过想先伸手问一下。

提前致谢!

罗伯特

您是在谈论调用不同自定义中包含的静态函数,还是调用另一个图形扩展中的实际实例方法?

这两种选择都是可能的——您所有的定制最终都会被编译并发布到同一个文件夹(App_RuntimeCode 和 bin 文件夹,如果您有任何 DLL),并且您可以安全地访问包含在不同的定制项目。

如果您想调用另一个图形扩展的实例方法,您首先需要检索可用的图形扩展实例:

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

1- 使用接口 locate/implement 调用代码。出于多种原因,我更喜欢接口方法而不是静态方法,但主要原因是:

a) 它们可以被覆盖或轻松委托给另一个实现。

b) 您可以确定您使用的是正确的方法。

c) 对于静态方法,您必须事先知道它所在的 class。对于已实现的方法,您不关心声明方法的 class 是什么。许多静态方法可以具有相同的签名但做不同的事情,因为它们没有绑定到已知接口。

d) 您可以将界面添加为单独自定义(与其他界面)共享的简单 dll。

e) 你不会污染你的其他接口,因为它是独立的。

f) 你宣布你做了什么,但没有宣布你是怎么做的。

g) 接口是保持良好解耦结构的最佳方式。

h) 它们是使用 Strategy Pattern

时的理想选择
public interface ISomeInterface {
    object DoSomething(); 
}


OR

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

2- 在尽可能多的定制包中尽可能多地实现您的界面。您的实现不需要是 PXGraph,但如果您希望与其共享代码或访问其他共享代码片段,它们可以。

public class SomeGraph : PXGraph<SomeGraph>, ISomeInterface {

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

3- 然后,在任何已加载代码的某些部分,找到您的实现并调用它们。就我而言,我使用了 Post-publish 接口:

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- 这是 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;
    }