重构一个方法来实现多个命名空间

Refactoring a Method to implement multiple namespaces

我正在尝试准备我的应用程序代码以接受第三方的年度更改 wsdl。我不能也无法控制这个 wsdl 的设计。此 wsdl 中的对象可能会更改、添加项目、删除项目等。但是,我仍然需要保留 wsdl.

的先前版本

我的计划是将当前的 wsdl 添加为服务参考,就像我对之前的 wsdl 所做的那样。

目前我有多种类似于下面的方法(包括下面的一种)。

使用 属性、TaxYear 来确定实际引用哪个 wsdl:"Service2015" 或 "Service2016"。我正在传递代表 wsdl 中的对象的通用对象,并为我在父方法中使用的那些对象传递 ref 参数。

像这样进行重构会造成很多膨胀,我忍不住认为必须有更好的方法来完成我正在尝试做的事情。

是否有使用 C# 执行此操作的更好方法,或者这是完成我需要完成的任务的最佳且最不方便的方法。

private static void RetrieveRequestObject(ref object objRequest, object objBusinessHeader, object objSecurityHeader, object objManifestHeader, object objFormData)
{
    if (TaxYear.Equals(2015))
    {
        objRequest = new Service2015.BulkRequestTransmitterRequest()
        {
            ACABusinessHeader = (Service2015.ACABulkBusinessHeaderRequestType)objBusinessHeader,
            Security = (Service2015.SecurityHeaderType)objSecurityHeader,
            ACATransmitterManifestReqDtl = (Service2015.ACATrnsmtManifestReqDtlType)objManifestHeader,
            ACABulkRequestTransmitter = (Service2015.ACABulkRequestTransmitterType)objFormData
        };
    }
    else if (TaxYear.Equals(2016))
    {
        objRequest = new Service2016.BulkRequestTransmitterRequest()
        {
            ACABusinessHeader = (Service2016.ACABulkBusinessHeaderRequestType)objBusinessHeader,
            Security = (Service2016.SecurityHeaderType)objSecurityHeader,
            ACATransmitterManifestReqDtl = (Service2016.ACATrnsmtManifestReqDtlType)objManifestHeader,
            ACABulkRequestTransmitter = (Service2016.ACABulkRequestTransmitterType)objFormData
        };
    }
}

尝试使用反射做这样的事情。

示例:

namespace Whosebug
{
    class Program
    {
        static void Main(string[] args)
        {
            int objBusinessHeader = 1,
            objSecurityHeader = 2,
            objManifestHeader = 3,
            objFormData = 4;

            var obj = (IService)RetrieveRequestObject(2010, objBusinessHeader,
                objSecurityHeader,
                objManifestHeader,
                objFormData);

            Console.WriteLine(obj.GetValues());


            var obj2 = (IService)RetrieveRequestObject(2011, objBusinessHeader,
                objSecurityHeader,
                objManifestHeader,
                objFormData);

            Console.WriteLine(obj2.GetValues());

            Console.ReadKey();
        }

        private static object RetrieveRequestObject(int taxYear, object objBusinessHeader,
            object objSecurityHeader, object objManifestHeader, object objFormData)
        {
            var serviceInstance = Activator.CreateInstance("Whosebug",
                "Whosebug.Service" + taxYear).Unwrap();

            var serviceInstanceType = serviceInstance.GetType();

            var aCABusinessHeaderInfo = serviceInstanceType.GetProperty("ACABusinessHeader");
            var securityInfo = serviceInstanceType.GetProperty("Security");
            var aCATransmitterManifestReqDtlInfo = serviceInstanceType.GetProperty("ACATransmitterManifestReqDtl");
            var aCABulkRequestTransmitterInfo = serviceInstanceType.GetProperty("ACABulkRequestTransmitter");

            aCABusinessHeaderInfo.SetValue(serviceInstance, objBusinessHeader, null);
            securityInfo.SetValue(serviceInstance, objSecurityHeader, null);
            aCATransmitterManifestReqDtlInfo.SetValue(serviceInstance, objManifestHeader, null);
            aCABulkRequestTransmitterInfo.SetValue(serviceInstance, objFormData, null);

            return serviceInstance;
        }
    }

    interface IService
    {
        string GetValues();
    }

    class Service2011 : IService
    {
        public int ACABusinessHeader { get; set; }
        public int Security { get; set; }
        public int ACATransmitterManifestReqDtl { get; set; }
        public int ACABulkRequestTransmitter { get; set; }

        public string GetValues()
        {
            return $@"Service 2011 - {ACABusinessHeader} {Security} {ACATransmitterManifestReqDtl}
                {ACABulkRequestTransmitter}";
        }
    }

    class Service2010 : IService
    {
        public int ACABusinessHeader { get; set; }
        public int Security { get; set; }
        public int ACATransmitterManifestReqDtl { get; set; }
        public int ACABulkRequestTransmitter { get; set; }

        public string GetValues()
        {
            return $@"Service 2010 - {ACABusinessHeader} {Security} {ACATransmitterManifestReqDtl}
                {ACABulkRequestTransmitter}";
        }
    }
}

PS - 可能存在更好的解决方案,目前我想不出更好的解决方案

在与 Web 服务所有者通信后,我发现我不必处理不同的端点或 .wsdl 文件的年度版本。无论年份如何,传输都发生在同一端点上,并且为了验证年份之间的架构,Web 服务的所有者检查传输清单中的 TaxYear 元素以确定要验证的架构。

为了适应这一点,我有 2 个单独的 XML "template" 文件,每个所需的纳税年度一个:2015 年和 2016 年。然后我的应用程序将根据我们提供的数据确定使用哪个模板正在尝试传输(通过清单中使用的 TaxYear 的值)。

我根据表单数据中可能存在的所有元素手工创建了这些模板 XML。任何重复的元素组只有一个单一的实例。在应用程序中创建了这些的多个实例。

我的应用程序读取 XML 模板并将在其中找到的虚拟值替换为从我们的数据中检索到的值。我从架构版本指定的 XML 中删除了任何未使用或无效的元素; create/clone 我们必须重复的任何元素(例如 1095-C 和 1094-C 表格的第 3 部分)。到目前为止,这种方法在初始测试中似乎运行良好。