问题:当我在父类中调用ValidateDynData时,程序流不会进入ValidateDynData的子类实现。
我使用反射创建了我的班级实例。当我从另一个项目调用子类中的方法时,它会在子类中使用正确的方法(而不是父类的同名方法),所以看起来这样设置正确。
这是反射部分在我的其他项目/类中的样子:
** Note 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时,它可能是一个问题: 变量................................................. .value的
base:{GenericCrWriter.GenericPC} ...... CrWriter.PC
baseInst:............................................. ... GenericCrWriter.GenericPC
但是,_assembly指的是Ko / PC而不是Generic / GenericPC。
另外,我的_assembly.GetType看起来不错。我的Generic / parent没有任何名为CrWriter.PC
的东西我正在尝试使用子类方法而不是父类来处理某些子类的情况。由于某种原因,我得到了父类方法,但它永远不会到达子句中的覆盖。有什么想法吗?我一直指的是Calling child class method from parent 但它没有达到孩子的方法。
在我的儿童班(Ko)的PC.cs中:
** Note 3/8/2013:PC.cs在Ko visual studio项目中。 **这包含显示的表单 ** Note 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中:
** Note 3/8/2013:GenericPC在Generic visual studio项目中。 ** Note 3/7/2013当子类调用父类初始化重要数据时,父类显示它的形式和字段(我认为简历布局显示它)。接下来,我们在表单上输入数据,包括Ko的自定义数据,然后我们点击表单上的按钮(btn_Lock_Config_Click),它需要处理并验证它的数据。我添加了更多方法来获得流感。父母比儿童(未示出)有更多方法,包括尝试/捕获等。
//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的子类实现?这是我的代码中唯一一个我试图让子类重写父实现的区域,所以我不确定我做错了什么?
我检查了子项目/类中引用的Generic.dll的正确版本。我在儿童班做了一个干净的构建。应该检查的任何其他二进制文件?我的反思有问题吗?我对ValidateDynData的虚拟/覆盖使用有什么问题吗?
更新: 我一直在查看代码,并通过创建父/基类的实例来流入父类。所以我认为这就是为什么当我在父类中调用它时,我没有进入在子类中重写的ValidateDynData。有没有另一种方法来获取父方法而不创建父实例?
GenericPC baseInst = new GenericPC();
return baseInst.GetPC(cbInst, dllSel, templ, dll, cert0, slaveIndex, BoxID);
**更新3/7/13: 也有可能的问题是,我按下父窗体上的一个按钮,开始一个新线程,这样做,它不知道子类,所以这就是为什么当我调用ValidateDynData方法时,流不会到达子节点
答案 0 :(得分:1)
简短的回答:只需删除所有可怕的代码并重新开始。
更长的答案:
// (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)
…
}
}
对标记的代码行的评论:
PC
声明为GenericPC
的后代。到目前为止一切顺利。GenericPC
实例,其中无事可做与您正在使用的PC
实例GetPC
,PC
实例的方法,然后在GetPC
的完全不同的实例中调用GenericPC
;与原始PC
实例没有任何共同之处!PC
实例;但是,当你有效地调用某些愚蠢的GenericPC
实例的方法时,这种情况永远不会发生!我的建议是阅读一本关于面向对象编程的书,它提供了C#中的示例。看起来你甚至错过了继承点,这是OOP中的基本概念之一。
要解决此问题,您需要删除 baseInst
的声明,并使用base
keyword替换对baseInst
方法的所有调用。然后,您的代码将实际调用在同一实例 中的祖先类中声明的方法。大多数方法也应在virtual
中声明为GenericPC
,并且override
中必须PC
。
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)
{
…
}
}