C# 关于抽象的建议
我正在编写一些代码,其中有一个抽象类,它有一些核心属性和一个Run(int-index)方法。然后,我创建新类型来继承它。这些新类型可以有多个方法,可以根据传入的索引调用这些方法C# 关于抽象的建议,c#,abstraction,C#,Abstraction,我正在编写一些代码,其中有一个抽象类,它有一些核心属性和一个Run(int-index)方法。然后,我创建新类型来继承它。这些新类型可以有多个方法,可以根据传入的索引调用这些方法 public abstract class BaseClass { public abstract void Run(int index); } public class Class1 : BaseClass { public override void 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调用,例如,单击菜单。所以我可能有一个1班和一个2班。Class1可能有3个方法,因此我可以调用run(0)。。。在上面运行(2)。类2可能只有一个内部方法,所以我只调用run(0)。也许我需要为每个类保留一个int集合,作为方法的映射。可能还必须向该集合添加字符串,以保存菜单项等的友好名称
您能想出一种方法来实现这种类型的映射,同时保持尽可能多的抽象吗?有没有比我现在的想法更好的方法呢?一种方法:
您可以改用接口:
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());
这似乎很合适,因为您已经知道原始版本传递的
索引是什么。这只是将它从基于int
移动到基于interface
(最后代码也更少)。让我进一步解释一下。这里有一个稍微详细一点的版本,我正在尝试做什么。您可以在这里看到,我的抽象类有一个索引列表,用于指向派生类中的正确方法,您可以看到我在UI中加载类型和创建菜单项的位置。我正在使用这个ItemPointer列表,并将ItemPointer传递给标记属性等。不知何故,这一切都感觉有点错误
我希望整个事情都可以扩展。我可能想添加一个Class2、Class3等所有继承基类的类。我可能还想使用基类创建插件。任何派生类都将至少有一个但可运行的方法,但可能有许多。这里的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);
}
}
}
}
公共抽象类基类
{
public List ItemPointers=new List();
公开摘要无效运行(int索引);
}
公共类项指针
{
公共int索引{get;set;}
公共字符串类类型{get;set;}
公共字符串UIDescription{get;set;}
}
公共类1:基类
{
公共类别1()
{
添加(新的ItemPointers{Index=0,ClassType=this.GetType().Name,UIDescription=“MethodA Description”});
添加(新的ItemPointers{Index=1,ClassType=this.GetType().Name,UIDescription=“MethodB Description”});
}
公共覆盖无效运行(整数索引)
{
如果(索引==0)
{
方法a();
}
else if(索引==1)
{
方法b();
}
}
私有无效方法a()
{
//做事
}
私有无效方法b()
{
//做事
}
}
公共类UIForm
{
私有列表基类;
//Formload事件加载所有基类类型(包括在form init期间通过反射加载的插件等),然后调用loadUIitems
私有void LoadUIItems()
{
foreach(基类bc在_基类中)
{
foreach(bc.ItemPointers中的var p)
{
ToolStripMenuItem t=新ToolStripMenuItem(p.UIDescription);
t、 单击+=新建事件处理程序(工作菜单单击);
t、 Tag=p;
actionsToolStripMenuItem.DropDownItems.Add(t);
}
}
}
无效工作菜单单击(对象发送者,事件参数e)
{
ToolStripMenuItem t=(ToolStripMenuItem)发送方;
ItemPointer p=(ItemPointer)t.Tag;
foreach(基类bc在_基类中)
{
if(bc.GetType().Name==p.ClassType)
{
bc.Run(p.Index);
}
}
}
}
在你的位置上,我可能倾向于尝试这样做:
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
我想你忘了在每个类中都包含:IRunnableSomething
。我确实这样做了。直接在浏览器中键入的危险!:)非常感谢你的回复,但你已经失去了我。界面的意义是什么?假设MyRunnableB类有4个我可能想要运行的方法,我现在必须为每个方法创建类型?例如,如果我想用插件扩展项目,会发生什么?@user2026382这通常是一个很好的信息,可以包含在您的问题中。这个回答似乎完全符合你最初的问题。。但如果您打算扩展它,则不会。问题似乎是“我发明了Windows消息循环…现在是什么?”-我建议跳过这些最初的痛苦版本,直接使用一些最近的强类型事件事件机制。。。