简体   繁体   English

我如何重构这两个C#函数来从他们所处理的特定类属性中抽象出它们的逻辑?

[英]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? 如何重写以下两个函数以尽可能多地抽象出算法,以便我可以在一个地方对逻辑进行更改?

SetBillingAddress SetBillingAddress

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: 这是第二个:

SetShippingAddress SetShippingAddress

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.

相关问题 如何在C#中通过接口实现此抽象类/属性逻辑? - how to Implement this Abstract Class/properties logic by Interface in C#? 如何从一个SET方法C#设置两个类属性 - How do I set two class properties from one SET method c# 如何从派生的 class (C#) 中的抽象 class 调用动作? - How do I invoke an Action from an abstract class in a derived class (C#)? C#从抽象类访问基类变量/函数 - C# Access base class variables/functions from abstract class 如何在C#中从两个抽象方法中仅实现抽象类中的一个方法? - How to to implementing only one methods from abstract class out of two abstract methods in C#? 如何编写指定创建逻辑的接口或抽象类? - How do I write an interface or abstract class that specifies creation logic? 在C#中,如何从派生类构造函数访问派生类的属性? - In C# how do I access the properties of a derived class from the derived class constructor? 不知道如何从 C# 中声明为抽象类类型的对象中检索属性 - Don't kwow how to retrieve properties from objects declared as abstract class type in C# 如何在C#.NET中为子类设置特定属性? - How do I set specific properties for a subclass in C# .NET? 如何使 class 像来自不同库的两个类一样,具有基本相同的功能? - How do I make a class acting like two classes from different libraries, with basically the same functionallity?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM