建议抽象

时间:2013-08-24 01:08:31

标签: 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)
    {
        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,我猜这是方法的映射。可能还需要在此集合中添加一个字符串,以保存菜单项等的友好名称。

你能想到一种方法来实现这种类型的映射,同时保持尽可能多的抽象吗?我现在的想法是否有更好的方法来解决这个问题?

3 个答案:

答案 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