在获取父类调用子类方法时遇到问题 - 使用了反射



问题:当我在父类中调用ValidateDynData时,程序流不会进入ValidateDynData的子类实现。

我使用反射创建我的类实例。 当我从另一个项目调用子类中的方法时,它会在子类中以正确的方法结束(而不是父类的同名方法(,因此看起来设置正确。

这是我的其他项目/类中的反射部分的样子:

**注意 3/7/2013:我添加了更多信息,以便您可以大致了解这一点。 它获取框数,循环遍历框数,并为每个框创建一个控件并向窗体添加一个选项卡。 这是主要的 CTool 视觉工作室项目,是项目中的一个类,它是一个表单。当我按下窗体上的按钮时,带有我稍后要创建的子类的信息(已选择(,它会转到此方法 CreatTabs((:

        cb = new CB();
        int errValue = cb.FindUsbHid(ref HWndBoxID); //see how many boxes there are
        if (errValue == 0 && HWndBoxID[0, 1] != 0)
        {
            for (int i = 0; i < cb.cbInfos.Length; i++)
            {
                if (controls[i] == null)
                {
                    CB cb1 = new CB(); //need one for each box found or concurrent programming will fail
                    errValue = cb1.FindUsbHid(ref HWndBoxID); //need to do for each box to get all info
                    /////////////////////////////////////////
                    if (errValue == 0)
                    {
                       _assembly = Assembly.LoadFrom(programDll);
                       _type = _assembly.GetType("CrWriter.PC");
                       _objectInstance = Activator.CreateInstance(_type);
                       _parameters = new Object[] { cb1, programDll, templateArr, itsDll, cert, i, cb1.cbInfos[i].boxID };
                       controls[i] = new Control();
                       //The following lands in my child's GetPC method
                       //My parent also has a method called GetPC and that is called from the child. 
                       //Then, most of the program flow is in the parent until I need to call ValidateDynData,
                       //discussed below
                       controls[i] = (Control)_type.InvokeMember("GetPC", BindingFlags.Default | BindingFlags.InvokeMethod, null, _objectInstance, _parameters);
                       controls[i].Dock = DockStyle.None;
                       this.Controls.Add(controls[i]); 
                       TabPage newPage = new TabPage(string.Format("{0}:{1}", cb1.cbInfos[i].usbHandle, cb1.cbInfos[i].boxID));
                        Console.WriteLine("frmUserForm::CreateTabs - Making new tab with cb.cbInfos[i].usbHandle:" + cb1.cbInfos[i].usbHandle + " and cb.cbInfos[i].boxID:" + cb1.cbInfos[i].boxID);
                        InitializeControls(controls[i]);
                        tabCtrlMain.Size = controls[i].Size;
                        tabCtrlMain.Width += 20;
                        tabCtrlMain.Height += 100;
                        this.Width = tabCtrlMain.Width + 20;
                        this.Height = tabCtrlMain.Height + 50;
                        newPage.Controls.Add(controls[i]);
                        tabCtrlMain.TabPages.Add(newPage);
                     } //no err for this cb
                 } //controls not null
             } //for all cbInfo's
          }//if no err in general finding out how many cb's
          this.ResumeLayout();
          }

由于我对 GetPC 的调用位于子类而不是父类中,因此必须正确创建它。所以我不确定为什么它没有登陆正确的 ValidateDynData 方法。也许我需要以某种方式将我的对象投射到 programDll。当我运行程序并检查_objectInstance时,这可能是一个问题: 变量。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。价值

base: {GenericCrWriter.GenericPC} ......CrWriter.PC

基地:GenericCrWriter.GenericPC

但是,_assembly指的是Ko/PC,而不是Generic/GenericPC。

还有,我的_assembly。GetType看起来不错。我的泛型/父没有名为 CrWriter.PC 的东西

对于某些子类情况,我正在尝试使用子类方法而不是父类。出于某种原因,我得到了父类方法,但它永远不会到达子类中的覆盖。知道为什么吗?我一直在参考从父级调用子类方法但它没有达到孩子的方法。

在我的电脑中.cs子班(Ko(:

**注 3/8/2013:PC.cs 在 Ko visual studio 项目中。**注 3/7/2013:这是一个以孩子命名的独立视觉工作室项目,我们称之为 Ko。这里重要的类是PC.cs。除了将数据传递给父级,提供自定义文本框及其名称,验证稍后在父级表单中输入的数据外,它没有太多作用。 否则,大部分流都在父级中。我正在添加GetPC,setProgramName,setDTF方法。

    public partial class PC : GenericPC
    {
      String childDllName = "";  //I just added this recently but it doesn't seem useful
      GenericPC baseInst = new GenericPC();
      public Control GetPC(USB_Comm.CB cbInst, string dllSel, TemplateHApp.Templates.TEMPL[] templ, string dll, SC.SC.SITE c0, int slaveIndex, int BoxID)
       {
           childDllName = dll;
           //call parent class methods  
           setProgramName();
           setDTF();
           ProcessDynData();
           return baseInst.GetPC(cbInst, dllSel, templ, dll, cert0, slaveIndex, BoxID);
       }

       public void setProgramName()
       {
           Console.WriteLine("Ko  did stuff");
           //Update label on form
           var f = new F(); //F is a class in child class containing more info on it
           string temp = f.GetProgramName();
           baseInst.setProgramName(temp); //this is displayed on parent's form
       }
       public void setDTF()
       {
           var f = new F();
           string temp = f.DTF();
           baseInst.setDTF(temp);  //this is displayed on parent's form
       }
       private void ProcessDynamicData()
       {
           Console.WriteLine("Ko PC::ProcessDynamicData");
           Label lbl_dynData0 = new Label();
           Label lbl_dynData1 = new Label();
           lbl_dynData0.Text = "AT  .";
           lbl_dynData1.Text = "VL   .";
           lbl_dynData0.Location = new Point(57, 25);
           lbl_dynData1.Location = new Point(57, 45);
           Label[] lbl_dynData_Arr = new Label[4];
           lbl_dynData_Arr[0] = lbl_dynData0;
           lbl_dynData_Arr[1] = lbl_dynData1;
           TextBox tb_dynData0 = new TextBox();
           TextBox tb_dynData1 = new TextBox();
           tb_dynData0.Location = new Point(67, 25);
           tb_dynData1.Location = new Point(67, 45);
           tb_dynData0.Size = new Size(151,22);
           tb_dynData1.Size = new Size(151, 22);
           TextBox[] tb_dynData_Array = new TextBox[4];
           tb_dynData_Array[0] = tb_dynData0;
           tb_dynData_Array[1] = tb_dynData1;
           PC pc = this;  //Tried adding this to get past problem but it's not turned out useful
           //I think the way I access parent class from child is the problem of why flow in 
           //parent class isn't reaching overridden method in child when called:
           baseInst.addDynamicDataTextBoxes(tb_dynData_Array, lbl_dynData_Arr, childDllName, pc);
       }
       public override void ValidateDynData(TextBox[] tb_dynData_Array, ref int result)
       { //I added more info here, but it's probably too much info 3/7/2013
          Console.WriteLine("Ko PC::ValidateDynData");
          result = -610; 
          //AT
          if ((Convert.ToInt16(tb_dynData_Array[0].Text) >= 1) && (Convert.ToInt16(tb_dynData_Array[0].Text) <= 99))
              result = 0;
          //VL
          if (result == 0) 
            if ((Convert.ToInt16(tb_dynData_Array[1].Text) >= 69) && (Convert.ToInt16(tb_dynData_Array[1].Text) <= 100))
                result = 0;
            else
                result = -610;
        }  

在我的 GenericPC 中.cs父类:

**注 3/8/2013:GenericPC 属于 Generic visual Studio 项目。**注意 3/7/2013 当子类调用父类来初始化重要数据时,父类会显示它的表单和字段(我认为简历布局会显示它(。 接下来,我们在表单上输入数据,包括 Ko 的自定义数据,然后点击表单上的按钮 (btn_Lock_Config_Click(,它需要处理和验证它的数据。我添加了更多方法来获得流动的感觉。 父级中的方法比子级(未显示(多得多,包括 try/catch 等。

    //base
    public partial class GenericPC : UserControl
    {
    //class variables (wave your hands..too much info)
     public Control GetPC(USB_Comm.CB cbInstance, string dllSelected, TemplateHApp.Templates.TEMPL[] template, string dll, SC.SC.SITE c0, int slaveIndex, int boxID)
    {
        cb = cbInstance;
        SlaveIndex = slaveIndex;
        createControls();
        itsDll = dll;
        templateArr = template;
        return this; //return the control for the control array
    }    
    //called from child class
    public void setProgramName(string name)
    {
        Console.WriteLine("Generic setProgramName slaveIndex:" + SlaveIndex);
        lbl_Program_Name.Text = name;
    }
    //called from child class
    public void setDTF(string theDTF)
    {
        Console.WriteLine("Generic setDTF slaveIndex:" + SlaveIndex);
        lbl_Program_Name.Text += " ";
        lbl_Program_Name.Text += theDTF;
        lbl_Program_Name.Refresh();
    }
    public void addDynamicDataTextBoxes(TextBox [] tb_dynData, Label [] lblTitle, String childName, Object child)
    { 
        childHasDynamicData = true; //somebody's knocking
        itsChildName = childName; //child name isn't turning out to be useful here
        itsChild = child; //child isn't turning out to be useful here
        Console.WriteLine("Generic addDynamicDataTextBoxes slaveIndex:" + SlaveIndex);
        //Display what child wants
        for (int i = 0; i < tb_dynData.Length; i++)
        {
            //assumes calling code knows real estate and planned for it
            gb_dynamicData.Controls.Add(lblTitle[i]);
            gb_dynamicData.Controls.Add(tb_dynData[i]);
        }
        itsEnteredDynamicData = tb_dynData; //nothing entered yet
    }
    private void btn_Lock_Config_Click(object sender, EventArgs e)
    {
        int status = 1;
        Console.WriteLine("Generic btn_Lock slaveIndex:" + SlaveIndex);
        //it does some flagging and data checking, etc.
        status = processDynamicData();
    }
    private int processDynData()
    {
        int returnCode = 0;  //I'm setting it to desired value for example
        //processes data, puts it into data arrays, etc, 
        if ((returnCode >= 0) && childHasDynamicData)
            ValidateDynData(itsEnteredDynamicData, ref returnCode);
           //start here for problem...it never calls child method, as intended
    }
    public virtual void ValidateDynData(TextBox[] tb_dynData_Array, ref int result)
    {
        Console.WriteLine("Generic::ValidateDynData passing off to child to validate special data");
    } 

知道为什么当我在父类中调用 ValidateDynData 时,它不会进入 ValidateDynData 的子类实现?这是我的代码中唯一一个我试图让子类覆盖父实现的区域,所以我不确定我是否做错了什么?

我检查了通用的正确版本.dll在孩子的项目/类中被引用。我在儿童班上做了一个干净的构建。还有其他应该检查的二进制文件吗? 我的倒影有问题吗? 我对ValidateDynData的虚拟/覆盖使用有问题吗?

更新:我一直在查看代码,并通过创建父/基类的实例来流入父类。所以我认为这就是为什么我没有进入 ValidateDynData,当我在父类中调用它时,它在子类中被覆盖。有没有另一种方法可以在不创建父实例的情况下访问父级的方法?

    GenericPC baseInst = new GenericPC(); 
    return baseInst.GetPC(cbInst, dllSel, templ, dll, cert0, slaveIndex, BoxID); 

**更新 3/7/13:也有可能是我按下父窗体上的一个按钮,该按钮启动一个新线程,并且这样做,它不知道子类,所以这就是为什么当我调用 ValidateDynData 方法时流不会到达子类。

简短的回答:只需删除所有糟糕的代码并重新开始。

更长的答案:

// (1)
public partial class PC : GenericPC
{
    // (2)
    GenericPC baseInst = new GenericPC();
    public Control GetPC(…)
    {
        …
        // (3)
        return baseInst.GetPC(cbInst, dllSel, templ, dll, cert0, slaveIndex, BoxID);
    }
    public override void ValidateDynData(TextBox[] tb_dynData_Array, ref int result)
    {
        // (4)
        …
    }
}

标记代码行的注释:

  1. 此时,您将PC声明为GenericPC后裔。目前为止,一切都好。
  2. 在这里,您声明并实例化一个完全不同的GenericPC实例,该实例与您正在使用的PC实例无关。
  3. 你调用GetPC,一个PC实例的方法,而实例又在那个完全不同的GenericPC实例中调用GetPC;与原始PC实例没有任何共同之处!
  4. 最后,您希望控制流最终成为原始PC实例;但是,当您一直有效地调用一些愚蠢的GenericPC实例的方法时,这种情况永远不会发生!

我的建议是阅读一本关于面向对象编程的书,它提供了 C# 中的示例。似乎您甚至错过了继承点,这是 OOP 中的基本概念之一。


要修复它,你需要删除 baseInst 的声明,并将所有对 baseInst 方法的调用替换为 base 关键字。然后,您的代码实际上将调用在同一实例中的祖先类中声明的方法。此外,大多数方法应在GenericPC中声明为virtual,您必须在PCoverride它们。

public partial class PC : GenericPC
{
    public override Control GetPC(…)
    {
        …
        return base.GetPC(cbInst, dllSel, templ, dll, cert0, slaveIndex, BoxID);
    }
    public override void ValidateDynData(TextBox[] tb_dynData_Array, ref int result)
    {
        …
    }
}

相关内容

  • 没有找到相关文章

最新更新