为你做脑筋急转弯!
我正在开发一个模块化系统,模块A可能需要模块B而模块B也需要模块A.但是如果模块B被禁用,它将不执行该代码而不执行任何操作/返回null。
透视一点:
让我们说InvoiceBusinessLogic
在模块“核心”内。我们还有一个“电子商务”模块,它有一个OrderBusinessLogic
。然后InvoiceBusinessLogic
看起来像这样:
public class InvoiceBusinessLogic : IInvoiceBusinessLogic
{
private readonly IOrderBusinessLogic _orderBusinessLogic;
public InvoiceBusinessLogic(IOrderBusinessLogic orderBusinessLogic)
{
_orderBusinessLogic = orderBusinessLogic;
}
public void UpdateInvoicePaymentStatus(InvoiceModel invoice)
{
_orderBusinessLogic.UpdateOrderStatus(invoice.OrderId);
}
}
所以我想要的是:当启用模块“电子商务”时,它实际上会在OrderBusinessLogic
上做一些事情。如果没有,它根本就不会做任何事情。在这个例子中,它什么都不返回,所以它可以简单地什么也不做,在其他一些会返回某些东西的例子中,它会返回null。
笔记:
IServiceCollection
负责定义实现。IOrderBusinessLogic
的实现将导致运行时问题。所以我到目前为止有3个选项:
ExpandoObject
构建一个虚假的实现,并且在调用特定方法时不做任何操作或返回null。最后一个选项就是我现在所追求的:
private static void SetupEcommerceLogic(IServiceCollection services, bool enabled)
{
if (enabled)
{
services.AddTransient<IOrderBusinessLogic, OrderBusinessLogic>();
return;
}
dynamic expendo = new ExpandoObject();
IOrderBusinessLogic fakeBusinessLogic = Impromptu.ActLike(expendo);
services.AddTransient<IOrderBusinessLogic>(x => fakeBusinessLogic);
}
通过使用Impromptu Interface,我能够成功创建一个虚假的实现。但我现在需要解决的是动态对象还包含所有方法(主要是不需要的属性),但这些方法很容易添加。所以目前我能够运行代码并起床直到它将调用OrderBusinessLogic
,然后逻辑上会抛出该方法不存在的异常。
通过使用反射,我可以遍历界面中的所有方法,但是如何将它们添加到动态对象?
dynamic expendo = new ExpandoObject();
var dictionary = (IDictionary<string, object>)expendo;
var methods = typeof(IOrderBusinessLogic).GetMethods(BindingFlags.Public);
foreach (MethodInfo method in methods)
{
var parameters = method.GetParameters();
//insert magic here
}
注意:现在直接调用typeof(IOrderBusinessLogic)
,但稍后我会迭代某个程序集中的所有接口。
Impromptu有一个例子如下:expando.Meth1 = Return<bool>.Arguments<int>(it => it > 5);
但是我当然希望这是动态的,所以如何动态插入返回类型和参数。
我确实理解一个界面就像合同一样,并且应该遵循该合同,我也理解这是一种反模式,但在达到这一点之前已经进行了广泛的研究和谈判,对于我们想要的结果系统,我们认为这是最好的选择,只是有点缺失:)。
IOrderBusinessLogic
中使用任何形式的InvoiceBusinessLogic
。