C# 如何编写可重用函数来解析XML并返回对象的ArrayList,这些对象可以被重写以返回子类的ArrayList

C# 如何编写可重用函数来解析XML并返回对象的ArrayList,这些对象可以被重写以返回子类的ArrayList,c#,xml,oop,design-patterns,C#,Xml,Oop,Design Patterns,我正在编写一个可重用的实用程序类,其中包含一个函数,该函数将XML请求字符串作为参数,它应该解析XML响应并返回CompanyData对象的ArrayList public ArrayList ReadCompaniesData(string xmlRequest) 该函数将向会计应用程序公开的web服务发送XML请求,该服务将返回有关该应用程序托管的多个公司的一些信息 我可以创建一个名为CompanyData的对象,其中包含公司标准属性的成员。但有时,会计应用程序可以定制为包括公司的其他属性

我正在编写一个可重用的实用程序类,其中包含一个函数,该函数将XML请求字符串作为参数,它应该解析XML响应并返回CompanyData对象的ArrayList

public ArrayList ReadCompaniesData(string xmlRequest)
该函数将向会计应用程序公开的web服务发送XML请求,该服务将返回有关该应用程序托管的多个公司的一些信息

我可以创建一个名为CompanyData的对象,其中包含公司标准属性的成员。但有时,会计应用程序可以定制为包括公司的其他属性

在这种情况下,我将创建CompanyData的一个子类,例如:MyCompanyData,我需要在我的实用程序类的一个子类中重写ReadCompanyData方法。这个子类方法如何为公司的所有公共/标准属性调用基类方法,然后为特定的附加属性解析XML响应

问题是基类方法将返回CompanyData对象的ArrayList,而子类将需要返回MyCompanyData对象(子类)的ArrayList。我不想在子类方法中复制整个代码;只需附加代码即可解析定制公司的附加属性


通过基类方法,我还可以将原始XML响应作为额外的out参数返回,这样子类就可以解析额外的标记,但是如何将ArrayList中的对象类型从CompanyData更改为MyCompanyData呢?如果需要创建一个新对象,并将一个字段一个字段地从CompanyData复制到MyCompanyData,这将非常麻烦。

如果只需要枚举返回的集合,可以尝试将方法的返回类型更改为
IEnumerable
,它支持泛型协方差,可以使用扩展方法(ToList、Cast、OfType等)转换为列表或过滤所需类型, 将解析逻辑移到域类,并在Util类的模板化方法中实例化实类型。 类似这样的内容(我使用System.Xml.Linq中的类而不是原始文本):

class公司
{
公共字符串标题{get;set;}
公共虚拟空解析XML(XElement元素)
{
此.Title=elem.Element(“Title”).Value;
}
}
公司类别:公司
{
公共字符串地址{get;set;}
公共覆盖无效解析XML(XElement元素)
{
ParseXml(elem);
this.Address=elem.Element(“地址”).Value;
}
}
类公司直到
{
受保护的虚拟公司GenerateAlCompany()
{
返回新公司();
}
公共IEnumerable可读公司(XDocument文档)
{
IList companies=新列表();
foreach(document.Root.Elements()中的var elem)
{
var comp=发电机公司();
comp.ParseXml(elem);
增加(公司);
}
返回公司;
}
}
类派生的CompanyUtil:CompanyUtil
{
受保护的覆盖公司GenerateAlCompany()
{
返回新的DerivedCompany();
}
}

您使用的是什么版本的.NET?如果您没有被困在.NET 2之下,我将完全不使用
ArraList
,而是使用
List
,并使方法通用。即使您使用通用列表,您仍需要在编码时指定通用列表的类型,并且在填充到该列表中时需要实例化对象CompanyData。此对象不具有特定自定义公司的附加属性;所以我仍然会面临同样的问题。你只需要确定你需要创建什么类型的对象,然后你就可以使用泛型了。基类方法不能确定要创建的对象的类型。我是否可以传递一个字符串参数来指定对象的类型,并在此基础上实例化泛型列表和成员对象?你能举个小例子吗?你可以把自定义属性放到字典里。
 class Company
{
    public string Title { get; set; }

    public virtual void ParseXml(XElement elem)
    {
        this.Title = elem.Element("Title").Value;
    }
}

class DerivedCompany : Company
{
    public string Address { get; set; }
    public override void ParseXml(XElement elem)
    {
        base.ParseXml(elem);
        this.Address = elem.Element("Address").Value;
    }
}



  class CompanyUtil
{

    protected virtual Company GenerateRealCompany()
    {
        return new Company();
    }
    public  IEnumerable<Company>  ReadCompanies(XDocument document)
    {
        IList<Company>  companies=new List<Company>();
        foreach (var elem in document.Root.Elements())
        {
            var comp = GenerateRealCompany();
            comp.ParseXml(elem);
            companies.Add(comp);
        }
        return companies;
    }
}

class DerivedCompanyUtil:CompanyUtil
{
    protected override Company GenerateRealCompany()
    {
        return new DerivedCompany();
    }
}