繁体   English   中英

需要根据传入的类类型定位不同属性的 C# 通用方法的最佳实现

[英]Best implementation for a C# Generic Method that needs to target different properties depending on the class type being passed in

所以我有一种方法可以解析传入的地址字段,并且根据其长度,它需要写入一个或多个字段(不要问...需要 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 };
        }

您要做的是将地址分配给不同的属性(取决于不同的类型)。 对于它你不需要使用泛型类型,你只需要创建一个接口

   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);
}

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

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 之类的东西配置为能够将多种不同类型的地址对象映射到一个公共对象上并返回,特别是如果这是跨越应用程序层边界的问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM