[英]How do I refactor these two C# functions to abstract their logic from the specific class properties they are acting on?
I have two functions whose underlying logic is the same but in one case it sets one property value on a class and in another case it sets a different one. 我有两个函数,其底层逻辑是相同的,但在一种情况下,它在类上设置一个属性值,在另一种情况下,它设置不同的一个。 How can I rewrite the following two functions to abstract away as much of the algorithm as possible so that I can make changes in logic in a single place?
如何重写以下两个函数以尽可能多地抽象出算法,以便我可以在一个地方对逻辑进行更改?
private void SetBillingAddress(OrderAddress newBillingAddress)
{
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
OrderAddress oldBillingAddress = basketHelper.Basket.Addresses[basketHelper.BillingAddressID];
bool NewBillingAddressIsNotOldBillingAddress = ((oldBillingAddress == null) || (newBillingAddress.OrderAddressId != oldBillingAddress.OrderAddressId));
bool BillingAddressHasBeenPreviouslySet = (oldBillingAddress != null);
bool BillingAddressIsNotSameAsShippingAddress = (basketHelper.ShippingAddressID != basketHelper.BillingAddressID);
bool NewBillingAddressIsNotShippingAddress = (newBillingAddress.OrderAddressId != basketHelper.ShippingAddressID);
if (NewBillingAddressIsNotOldBillingAddress && BillingAddressHasBeenPreviouslySet && BillingAddressIsNotSameAsShippingAddress)
{
basketHelper.Basket.Addresses.Remove(oldBillingAddress);
}
if (NewBillingAddressIsNotOldBillingAddress && NewBillingAddressIsNotShippingAddress)
{
basketHelper.Basket.Addresses.Add(newBillingAddress);
}
basketHelper.BillingAddressID = newBillingAddress.OrderAddressId;
basketHelper.Basket.Save();
}
And here is the second one: 这是第二个:
private void SetShippingAddress(OrderAddress newShippingAddress)
{
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
OrderAddress oldShippingAddress = basketHelper.Basket.Addresses[basketHelper.ShippingAddressID];
bool NewShippingAddressIsNotOldShippingAddress = ((oldShippingAddress == null) || (newShippingAddress.OrderAddressId != oldShippingAddress.OrderAddressId));
bool ShippingAddressHasBeenPreviouslySet = (oldShippingAddress != null);
bool ShippingAddressIsNotSameAsBillingAddress = (basketHelper.ShippingAddressID != basketHelper.BillingAddressID);
bool NewShippingAddressIsNotBillingAddress = (newShippingAddress.OrderAddressId != basketHelper.BillingAddressID);
if (NewShippingAddressIsNotOldShippingAddress && ShippingAddressHasBeenPreviouslySet && ShippingAddressIsNotSameAsBillingAddress)
{
basketHelper.Basket.Addresses.Remove(oldShippingAddress);
}
if (NewShippingAddressIsNotOldShippingAddress && NewShippingAddressIsNotBillingAddress)
{
basketHelper.Basket.Addresses.Add(newShippingAddress);
}
basketHelper.ShippingAddressID = newShippingAddress.OrderAddressId;
basketHelper.Basket.Save();
}
My initial thought was that if I could pass a class's property by refernce then I could rewrite the previous functions into something like 我最初的想法是,如果我可以通过引用传递一个类的属性,那么我可以将之前的函数重写为类似的东西
private void SetPurchaseOrderAddress(OrderAddress newAddress, ref String CurrentChangingAddressIDProperty)
and then call this function and pass in either basketHelper.BillingAddressID or basketHelper.ShippingAddressID as CurrentChangingAddressIDProperty but since I can't pass C# properties by reference I am not sure what to do with this code to be able to reuse the logic in both places. 然后调用此函数并将basketHelper.BillingAddressID或basketHelper.ShippingAddressID作为CurrentChangingAddressIDProperty传递,但由于我无法通过引用传递C#属性,我不知道如何处理此代码以便能够在两个地方重用逻辑。
Thanks for any insight you can give me. 感谢您给我的任何见解。
You can pass lambda expressions: 您可以传递lambda表达式:
private void SetPurchaseOrderAddress(OrderAddress newAddress, Func<string> addressIDGetter, Action<string> addressIDSetter)
Call it like this: 像这样称呼它:
SetPurchaseOrderAddress(newAddress, () => basketHelper.BillingAddressID, a => basketHelper.BillingAddressID = a);
Send in a Func and an Action, one to get the property out, and another to set it again. 发送Func和Action,一个用于获取属性,另一个用于再次设置。
private void SetPurchaseOrderAddress(OrderAddress newAddress,
Func<BasketHelper, int> getAddId, Action<BasketHelper, int> setAddId) {}
Which would give something like: 这将给出类似的东西:
SetPurchaseOrderAddress(address,
bh => bh.Basket.Addresses[bh.BillingAddressID],
(bh,s) => bh.BillingAddressID = s);
You can use delegates to create a method that takes some simple behavior (such as setting a value of the property) as an argument. 您可以使用委托创建一个方法,该方法将一些简单的行为(例如设置属性的值)作为参数。 In C# 3.0, you can easily create a delegate using lambda expressions and in C# 2.0 you can do similar thing using anonymous delegates.
在C#3.0中,您可以使用lambda表达式轻松创建委托,在C#2.0中,您可以使用匿名委托来执行类似的操作。
In your example, you would write a method that takes Action<BasketHelper>
delegate - the delegate allows you to specify some operation that should be done with the BasketHelper
after you initialize it and before you save it: 在您的示例中,您将编写一个采用
Action<BasketHelper>
委托的方法 - 委托允许您指定在初始化之后和保存之前应使用BasketHelper
完成的一些操作:
private void SetBasketProperty(Action<BasketHelper> action) {
BasketHelper basketHelper = new BasketHelper(SiteConstants.BasketName);
// Code that is repeated for all similar methods
// Invoke the specific action
action(basketHelper);
basketHelper.Basket.Save();
}
To call this method in C# 3.0 you can write something like this: 要在C#3.0中调用此方法,您可以编写如下内容:
SetBasketProperty(basketHelper => {
basketHelper.ShippingAddressID = newShippingAddress.OrderAddressId;
});
The lambda expression simply provides the code that you want to run before calling Save
. lambda表达式只是提供了在调用
Save
之前要运行的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.