C#泛型方法的最佳实现,它需要根据传入的类类型来定位不同的属性

问题描述 投票:1回答:2

因此,我有一种方法可以解析传入的地址字段,并且根据其长度,它需要写入一个或多个字段(不要问...需要DB2旧式代码)。目前,我们为需要的每个类都实现了此方法,我想编写一个通用方法,我必须在某种程度上完成该方法。问题在于,尽管我们解析每个对象的地址字段的方式相同,但根据使用的属性名称不同,所使用的属性名称却有所不同。

然后这要求我检查传入的对象的类型,然后进行两次强制转换(ClassType)(object)以能够访问属性并正确设置它们,然后再次进行两次强制强制转换(T)(object)返回通用列表。

这是低效率的,并且基本上在某种程度上违背了使用泛型的目的。是否有更好的方法来获得相同的功能而不必进行类型检查和两次强制转换才能访问类属性?

public List<T> ParseLongNameStreetName<T>(List<T> myList)
        {
            myList.ForEach(item =>
            {
                if (item.GetType() == typeof(DP1)) {
                    DP1 castItem = (DP1)(object)item;
                    dynamic streetName = ParsedStreetName(castItem.MA1 + " " + castItem.MA2);

                    castItem.MA1 = streetName.add1;
                    castItem.MA2 = streetName.add2;
                    castItem.MA3 = streetName.add3;

                    item = (T)(object)castItem;
                }

                else if (item.GetType() == typeof(DI1))
                {
                    DI1 castItem = (DI1)(object)item;
                    dynamic streetName = ParsedStreetName(castItem.MA1 + " " + castItem.MA2);

                    castItem.MA1 = streetName.add1;
                    castItem.MA2 = streetName.add2;
                    castItem.MA3 = streetName.add3;

                    item = (T)(object)castItem;
                }
                else if (item.GetType() == typeof(DW1))
                {
                    DW1 castItem = (DW1)(object)item;
                    dynamic streetName = ParsedStreetName(castItem.AD1 + " " + castItem.AD2);

                    castItem.AD1 = streetName.add1;
                    castItem.AD2 = streetName.add2;
                    castItem.AD3 = streetName.add3;

                    item = (T)(object)castItem;
                }
            });

            return myList;
        }



private dynamic ParsedStreetName(string address)
        {
            string add1 = string.Empty;
            string add2 = string.Empty;
            string add3 = string.Empty;

            int addLen = address.Length;
            try
            {
                add1 = addLen > 30 ? address.Substring(0, 30) : address.Substring(0, addLen);
                add2 = addLen > 30 ? addLen > 60 ? address.Substring(29, 30) : address.Substring(30, addLen - 30) : "";
                add3 = addLen > 60 ? address.Substring(59, addLen - 60) : "";
            } catch(Exception ex)
            {
                Console.WriteLine(ex);
            }


            return new { add1, add2, add3 };
        }
c# generics generic-list
2个回答
1
投票

您正在尝试将地址分配给不同的属性(取决于不同的类型)。为此,您不需要使用通用类型,只需要创建一个接口

   public interface IAddressAssignable
   {
      string GetRawAddress();
      void AssignAddresses(string add1, string add2, string add3);
   }

使全部3个(DP1,DI1,DWXP111)实现该接口(具有不同的逻辑(不同的属性)。然后在您的ForEach()中

myList.ForEach(item =>
{
    dynamic streetName = ParsedStreetName(item.GetRawAddress());
    item.AssignAddresses(streetName.add1, streetName.add2, streetName.add3);
}

1
投票

我可能会考虑让地址从具有典型属性名称的基地址实体派生,并且/或者可能是设置相关细节的可重写方法。您的解析器可以将任何变量实体视为基地址类型,并设置属性,继承的实现将获取特定名称:

public class BaseAddress{
  protected string _buildingName;
  protected string _zipCode;

  public void SetAll(string b, string z){ // call this in your parser 
    _buildingName = b;
    _zipCode = z;
  }
}

public class WorkAddress:BaseAddress{
  public string Factory => _buildingName;
  public string PostCode => _zipCode;
}

public class HomeAddress:BaseAddress{
  public string HouseName => _buildingName;
  public string Zip => _zipCode;
}

甚至将解析例程构建到基类中,仅在操作上存在重大差异时才添加覆盖,这甚至是有意义的

从这个意义上讲,当您可以使用带有BaseAddress的方法时,您不需要具有使用所有不同地址类型的通用方法。我跳过了BaseAddress的属性,但是您可以通过这种方式使用BaseAddress进行添加-这完全是在“我的数据库上下文中,期望工厂表中存储的工厂地址具有这些列和主目录具有这些列的地址。“


作为替代,可以将诸如Automapper之类的东西配置为能够将多种不同类型的地址对象映射到一个普通的地址对象上,然后再将其映射回去,尤其是在您跨越应用程序层边界的问题时,尤其如此

© www.soinside.com 2019 - 2024. All rights reserved.