1

参考我之前的问题,故事开始于我有一堆 svcutil 生成的类。它们是从外部 WSDL 生成的。干得好:

第一个请求类:

public partial class getcarsRequest
{

    [System.ServiceModel.MessageHeaderAttribute(Namespace = "http://svc.datadomains.com/revision123_2/")]
    public CarsServiceApp.RequestHeader Header;

    [System.ServiceModel.MessageBodyMemberAttribute(Name = "getcarsRequest", Namespace = "carinfo", Order = 0)]
    public CarsServiceApp.getcars MessageWrap;

    public getcarsRequest()
    {
    }

    public getcarsRequest(CarsServiceApp.RequestHeader Header, CarsServiceApp.getcars getcarsRequest1)
    {
        this.Header = Header;
        this.MessageWrap = getcarsRequest1;
    }
}

public partial class getcars
{

    private MessageType messageField;

    private MessageDataGetcarsRequest messageDataField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
    public MessageType Message
    {
        get
        {
            return this.messageField;
        }
        set
        {
            this.messageField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
    public MessageDataGetcarsRequest MessageData
    {
        get
        {
            return this.messageDataField;
        }
        set
        {
            this.messageDataField = value;
        }
    }
}

public partial class MessageDataGetcarsRequest
{

    private AppDataGetcarsRequest appDataField;

    private AppDocumentType appDocumentField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
    public AppDataGetcarsRequest AppData
    {
        get
        {
            return this.appDataField;
        }
        set
        {
            this.appDataField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
    public AppDocumentType AppDocument
    {
        get
        {
            return this.appDocumentField;
        }
        set
        {
            this.appDocumentField = value;
        }
    }
}

public partial class AppDataGetcarsRequest
{
    private string addressField;

    private int codeField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
    public address address
    {
        get
        {
            return this.addressField;
        }
        set
        {
            this.addressField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
    public int code
    {
        get
        {
            return this.codeField;
        }
        set
        {
            this.codeField = value;
        }
    }

}

第二:

public partial class getdriversRequest
{

    [System.ServiceModel.MessageHeaderAttribute(Namespace = "http://svc.datadomains.com/revision123_2/")]
    public carsServiceApp.RequestHeader Header;

    [System.ServiceModel.MessageBodyMemberAttribute(Name = "getdriversRequest", Namespace = "driverinfo", Order = 0)]
    public carsServiceApp.getdrivers MessageWrap;

    public getdriversRequest()
    {
    }

    public getdriversRequest(carsServiceApp.RequestHeader Header, carsServiceApp.getdrivers getdriversRequest1)
    {
        this.Header = Header;
        this.MessageWrap = getdriversRequest1;
    }
}

public partial class getdrivers
{

    private MessageType messageField;

    private MessageDataGetdriversRequest messageDataField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
    public MessageType Message
    {
        get
        {
            return this.messageField;
        }
        set
        {
            this.messageField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
    public MessageDataGetdriversRequest MessageData
    {
        get
        {
            return this.messageDataField;
        }
        set
        {
            this.messageDataField = value;
        }
    }
}

public partial class MessageDataGetdriversRequest
{

    private AppDataGetdriversRequest appDataField;

    private AppDocumentType appDocumentField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
    public AppDataGetdriversRequest AppData
    {
        get
        {
            return this.appDataField;
        }
        set
        {
            this.appDataField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
    public AppDocumentType AppDocument
    {
        get
        {
            return this.appDocumentField;
        }
        set
        {
            this.appDocumentField = value;
        }
    }
}

public partial class AppDataGetdriversRequest
{
    private string nameField;

    private int customerCodeField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
    public name name
    {
        get
        {
            return this.nameField;
        }
        set
        {
            this.nameField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
    public int customerCode
    {
        get
        {
            return this.customerCodeField;
        }
        set
        {
            this.customerCodeField = value;
        }
    }

}

这只是 svcutil 生成的两个实体。还有其他实体与这两个类似,仅在大多数基础AppData属性上有所不同。我编写了一个强大的 shell 脚本来准备原始生成的文件重命名某些字段,但这还不足以完成所有工作。

我怎样才能组成班级团结?看来我应该使用参数化接口......我需要统一的类结构来设计常见的有用功能,例如检查请求是否正确或从头开始创建请求。

提前谢谢各位!我的大脑都为那些东西沸腾了。


问题编辑#1

好的,伙计们,这是我想要的。假设我们要检查任何服务方法的正确性请求。如果某个请求的AppData属性不为空,我们应该认为该请求是正确的。实际上,我们最好有一些通用的类方法来进行这种检查。AppData但是,如果任何请求类具有不同的属性类型,我们如何创建该方法呢?

让我们看一下两个生成的类,并为每个 AppData 属性绘制一些假想的路径。

对于第一类,我们有 getcarsRequest(在括号中,我们有适当的类类型):

请求(getcarsRequest)-> MessageWrap(getcars)-> MessageData(MessageDataGetcarsRequest)-> AppData(AppDataGetcarsRequest)

对于第二个我们有下一条路径:

请求(getdriversRequest)-> MessageWrap(getdrivers)-> MessageData(MessageDataGetdriversRequest)-> AppData(AppDataGetdriversRequest)

那么我们如何重新设计并将它们简化为一些通用接口呢?如果我们为这两个类有一个合适的通用接口,我们可以编写一些CheckRequest(IRequest<T> request).

我希望我在这里得到一些澄清。任何建议/句子将不胜感激。如果您对我有任何疑问,请随时将它们带给我。

4

3 回答 3

3

据我了解,您有两个有效复制的类结构:汽车和驾驶员。您应该专注于重构输入 wsdl(我们还没有看到),而不是修改生成的类。

为了消除这种重复,考虑制作两个对象:汽车和司机,并重组 wsdl 操作,使它们可以对任一类型的对象进行操作。在面向对象的术语中,car 和 driver 都应该继承自同一个基类,该基类将具有可由 wsdl 操作调用的抽象方法。然后需要在汽车和驱动程序派生/具体类中实现这些抽象方法。

于 2012-05-07T12:56:58.680 回答
0

如果您无法编辑 WSDL 以提供通用类型,我看到两种可能性:

  1. 您可以创建使用已知类型参数化的通用包装类。这些类将模仿具体类的结构(由 svcutil 生成),包括它们的层次结构。然后将原始对象包装在适当的包装器中,并从那时起使用包装器。

    优点:与包装类的交互类似于原始(原始)对象,没有太多运行时开销。

    缺点:您需要在 WSDL 更改时创建和维护原始(原始)对象的类布局/层次结构。

  2. 或者,您可以使用反射在对象上调用适当的方法——您需要根据具体类型计算方法名称(例如callFunction(o, "get", "car")调用((GetCarsRequest)o).getCars())。

    优点:您不需要创建和维护阴影类型层次结构来匹配原始类型布局/层次结构。

    缺点:通常反射比通过编译的字节码获得相同的结果要慢得多。

这两种方法都要求您始终确定要处理的对象类型,这应该不是问题,因为您当前的设置中已经存在这种情况。

于 2012-05-09T19:24:07.253 回答
0

重构可能是最好的选择,但如果它不可行,您可以利用它们的优势partial并添加一个接口。

public IData<TRequest>  {
    T AppData { get; set; }
    bool IsValid { get; }
}
public partial class MessageDataGetdriversRequest : IData<AppDataGetcarsRequest>
{
    bool IsValid { get { this.AppData != null; } }
}
public partial class MessageDataGetdriversRequest: IData<AppDataGetdriversRequest>
{
    bool IsValid { get { this.AppData != null; } }
}

然后你可以做var data = getcars.MessageData;var data = getdrivers.MessageData;,然后检查data.IsValid

也可以IsValid作为扩展方法实现 onthis IData<T>而不是 的属性IData,在这种情况下,您甚至不需要为每个类声明它(但它将是一个方法,而不是一个属性)。

public partial class MessageDataGetdriversRequest : IData<AppDataGetcarsRequest> { }
public partial class MessageDataGetdriversRequest: IData<AppDataGetdriversRequest> { }

public static bool IsValid(this IData<T> data)
{
    return data.AppData != null;
}
于 2012-05-09T19:45:38.983 回答