【问题标题】:C# call derived class property using base class referenceC# 使用基类引用调用派生类属性
【发布时间】:2023-03-18 08:09:02
【问题描述】:

我有一堂课RequestDetail。有 2 个类 classA 和 classB 派生自它,因此每个类都有自己的属性:

public partial classA : RequestDetail { ..... }
public partial classB : RequestDetail { ..... }

我正在写一个方法CreateMethod1(ClassA a)CreateMethod2(ClassB b)

除了一些细微的差别外,这两种方法都做同样的事情。我想编写一个泛型方法并通过在 CreateMethod1 和 CreateMethod2 中传递引用来调用该方法。

谁能帮我做这件事?

谢谢

编辑:

我所排除的是我收到了一个 WSDL,它在生成时为我提供了四个独立的类,这些类继承自具有大约 20 个属性的基类。它们仅略有不同,确切地说,两个类包含相同的字段(IsUrgent),第三个包含(Ticket 和 Reason),第四个包含(BudgetCode) 然而,所有实现的持久性完全相同。我不想创建 4 个单独的方法来保存相同的信息。

值得注意的是这些类是部分的。

xsd 如下所示

<xs:complexType name="ClassA">
    <xs:complexContent>
      <xs:extension base="IARequestDetails">
        <xs:sequence>
          <xs:element name="IsUrgent" type="IAUrgency"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="ClassB">
    <xs:complexContent>
      <xs:extension base="IARequestDetails">
        <xs:sequence>
          <xs:element name="BudgetCode" type="ProjectBudgetCode"/>
          <xs:element name="IsUrgent" type="IAUrgency"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

【问题讨论】:

  • 那么你能不能只写方法来获取RequestDetail?目前还不清楚这里有什么问题......
  • @JonSkeet 我已经更新了上面的问题。抱歉回复晚了。

标签: c#


【解决方案1】:

你应该在基类中创建一个virtualabstract方法,在每个派生类中重写它,然后正常调用。

【讨论】:

    【解决方案2】:

    将您的基类指定为抽象,在其中编写方法“CreateMethod”并在需要不同行为的地方创建抽象函数(如果行为覆盖是可选的,则为虚拟函数)。覆盖抽象函数,在其中添加所需的行为。

    public abstract RequestDetail
    {
        public void CreateDetail()
        {
            CustomBehavior();
        }
        protected abstract CustomBehavior();
    }
    public RequestDetailA : RequestDetail
    {
        protected override void CustomBehavior()
        {
            // Foo
        }
    }
    

    【讨论】:

    • 实际上我正在编写一个使用代理类的网络服务方法。基类和派生类在代理类中定义。 webservice 方法将派生类作为参数。请在下面找到代理类和网络服务供您参考。
    • 基类和派生类都有属性而不是方法。派生类、基类和有方法的接口都在使用wsdl.exe生成的代理类中
    【解决方案3】:

    如果这些方法在 RequestDetails 中,我建议你让它接收一个 RequestDetail,在该方法中,你可以从 RequestDetail 调用一个抽象方法来实现这些细微的差异,并且 ClassA 和 ClassB 中的每一个都实现了不同的方法,例如

    class RequestDetail{
        public void CreateMethod(RequestDetails reqD){ 
            //do what you need
            AbstCreateMethod(reqD);
        }
        public abstract void AbstCreateMethod(RequestDetails reqD);
    
    }
    
    class ClassA : RequestDetails{
        public void AbstCreateMethod(RequestDetails reqD){
            //do classA things  
        }
    }
    
    class ClassB : RequestDetails{
        public void AbstCreateMethod(RequestDetails reqD){
            //do classB things  
        }
    }
    

    如果它在另一个类中,请遵循与此类似的解决方案,但使用具有这些方法的类。 有关这方面的更多信息,请阅读设计模式Template method

    【讨论】:

    • 实际上我正在编写一个使用代理类的webservice方法。基类和派生类在代理类中定义。 webservice 方法将派生类作为参数。请在下面找到代理类和网络服务供您参考。
    【解决方案4】:

    这是一个使用部分类、接口和通用约束的解决方案……您需要为每个子类构建需要在 Params 实现中返回的参数列表,超类属性自然可用。

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
    
    namespace ConsoleApplication3
    {
        public interface IABInterface
        {
            //Could be your SqlParameters
            string[] Params { get; }
        }
    
        public partial class IARequestDetails
        {
            public int One
            {
                get; set; 
            }
    
            public int Two
            {
                get;set;
            }
        }
    
        public partial class ClassA : IARequestDetails
        {
            public int IsUrgent 
            {
                get;set;
            }
        }
    
        public partial class ClassB : IARequestDetails
        {
            public int BudgetCode
            {
                get;
                set;
            }
    
            public int IsUrgent
            {
                get;
                set;
            }
        }
    
        public partial class ClassA : IABInterface
        {
            #region IABInterface Members
    
            public string[] Params
            {
                //Create your list of parameters
                get { return null; }
            }
    
            #endregion
        }
    
        public partial class ClassB : IABInterface
        {
            #region IABInterface Members
    
            public string[] Params
            {
                get
                {
                    return null;
                }
            }
            #endregion
        }
    
        public class Persist
        {
            public void Save<T>(T obj)
                where T : IARequestDetails, IABInterface
            {
                //Do you saving here ... 
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Persist persist = new Persist();
    
                persist.Save(new ClassA());
                persist.Save(new ClassB());
            }
        }
    }
    

    【讨论】:

    • 感谢您的回答,真的很有帮助。
    • 圣诞晚会,这有点技术挑战。部分类背后的全部原因是生成的代码要在其他地方更改......我相信还有很多其他方法可以解决这个问题(我没有考虑太多,但想到了扩展方法)
    【解决方案5】:
    class mybase 
    { 
       virtual void DoStuff(){...}
    
    }
    
    class Der1:mybase
    {
        virtual override void DoStuff(){
           base.DoStuff(); // Call the Common Code 
           .... Custom Code for this class
     }
    
     Der1 A = new Der1(); 
     mybase B = new Der1();
     A.DoStuff(); // this will call the derived version 
     B.DoStuff(); // So will this 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      • 2011-05-11
      • 2017-07-05
      • 2016-03-27
      相关资源
      最近更新 更多