我正在研究一些代码,我有一个抽象类,它有一些核心属性和一个Run(int index)方法。然后我创建继承这个的新类型。这些新类型可以有多个方法,可以根据传入的索引调用。
public abstract class BaseClass
{
public abstract void Run(int index);
}
public class Class1 : BaseClass
{
public override void Run(int index)
{
if (index == 0)
{
MethodA();
}
else if (index == 1)
{
MethodB();
}
}
private void MethodA()
{
//do stuff
}
private void MethodB()
{
//do stuff
}
}
我只是想知道是否有更好的方法来做到这一点。这些类型和方法将从UI调用,例如菜单点击。所以我可能有class1和class2。 Class1可能有3个方法,所以我可以调用run(0)... run(2)。 Class2可能只有一个内部方法,所以我只调用run(0)。也许我需要在每个类中保留一组int,我猜这是方法的映射。可能还需要在此集合中添加一个字符串,以保存菜单项等的友好名称。
你能想到一种方法来实现这种类型的映射,同时保持尽可能多的抽象吗?我现在的想法是否有更好的方法来解决这个问题?
答案 0 :(得分:1)
一种方式:
您可以使用界面:
public interface IRunnableSomething {
void Run();
}
public class MyRunnableA :IRunnableSomething
{
public void Run() {
// do stuff
}
}
public class MyRunnableB :IRunnableSomething
{
public void Run() {
// do stuff
}
}
然后在你的主要班级......
public override void Run(IRunnable runnable)
{
runnable.Run();
}
调用它的示例:
myInstanceOfMainClass.Run(new MyRunnableA());
这似乎很合适,因为您已经知道您使用原始版本传递的index
。这只是基于int
基于interface
的基础(最后也减少了代码)。
答案 1 :(得分:0)
让我再解释一下。这是我想要做的稍微冗长的版本。你可以在这里看到我的抽象类有指向派生类中正确方法的索引列表,你可以看到我在UI中加载类型和创建菜单项的位置。我正在使用这个ItemPointer列表并传递ItemPointers来标记属性等。这在某种程度上感觉有点不对劲。
我希望整个事情可以扩展。我可能想要添加继承BaseClass的Class2,Class3等。我可能还想使用BaseClass创建插件。任何派生类都将至少有一个但可运行的方法,但可能会有很多。所以这里的Class1只是一个例子。这有助于解释自己吗?请放轻松我,我正在学习,这就是我在这里问的原因。
我在这里做的很糟糕吗?还是可以的?或者,还有更好的方法?我猜这是我的问题。如果有更好的方法,我真的很感激一个例子。非常感谢大家的帮助。非常感谢。
public abstract class BaseClass
{
public List<ItemPointer> ItemPointers = new List<ItemPointer>();
public abstract void Run(int index);
}
public class ItemPointer
{
public int Index { get; set; }
public string ClassType { get; set; }
public string UIDescription { get; set; }
}
public class Class1 : BaseClass
{
public Class1()
{
ItemPointers.Add(new ItemPointer { Index = 0, ClassType = this.GetType().Name, UIDescription = "MethodA Description" });
ItemPointers.Add(new ItemPointer { Index = 1, ClassType = this.GetType().Name, UIDescription = "MethodB Description" });
}
public override void Run(int index)
{
if (index == 0)
{
MethodA();
}
else if (index == 1)
{
MethodB();
}
}
private void MethodA()
{
//do stuff
}
private void MethodB()
{
//do stuff
}
}
public class UIForm
{
private List<BaseClass> _baseClasses;
//Formload events load all baseclass types (including plugins via reflection during form init etc. Then call loadUIitems
private void LoadUIItems()
{
foreach (BaseClass bc in _baseClasses)
{
foreach (var p in bc.ItemPointers)
{
ToolStripMenuItem t = new ToolStripMenuItem(p.UIDescription);
t.Click += new EventHandler(WorkerMenu_Click);
t.Tag = p;
actionsToolStripMenuItem.DropDownItems.Add(t);
}
}
}
void WorkerMenu_Click(object sender, EventArgs e)
{
ToolStripMenuItem t = (ToolStripMenuItem)sender;
ItemPointer p = (ItemPointer)t.Tag;
foreach (BaseClass bc in _baseClasses)
{
if (bc.GetType().Name == p.ClassType)
{
bc.Run(p.Index);
}
}
}
}
答案 2 :(得分:0)
在你的位置上,我可能倾向于尝试做这样的事情:
void Main()
{
var a = new Class1();
var b = new Class2();
try
{
a.Run("Foo");
b.Run("Bar", "Yoda");
b.Run("Bat"); // throws exception
}
catch (Exception ex)
{
Console.WriteLine (ex.Message);
}
}
class Base
{
public void Run(string commandName, params object[] args)
{
var method = this.GetType().GetMethod(commandName);
if(method != null)
method.Invoke(this, args);
else
throw new Exception("the command " + commandName + " does not exist on " + this.GetType().Name);
}
}
class Class1 : Base
{
public void Foo()
{
Console.WriteLine ("I am foo");
}
}
class Class2 : Base
{
public void Bar(string str)
{
Console.WriteLine ("I am {0}", str);
}
}
<强>输出:强>
I am foo
I am Yoda
the command Bat does not exist on Class2