您可以在不同的自定义包上调用方法吗?
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;
}
我们有一个计划,我们需要在两个不同的定制包之间进行通信。所以我们有定制 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;
}