0

私は、いくつかのコア プロパティと 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 には内部メソッドが 1 つしかない場合があるため、run(0) を呼び出すだけです。メソッドへのマップとして推測する各クラスで、int のコレクションを保持する必要があるかもしれません。メニュー項目などのわかりやすい名前を保持するために、このコレクションに文字列を追加する必要がある場合もあります。

できるだけ多くの抽象化を維持しながら、このタイプのマッピングを実装する方法を考えられますか? 私の現在の考えよりも良い方法はありますか?

4

3 に答える 3

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です(最終的にはコードも少なくなります)。

于 2013-08-24T01:17:24.747 に答える
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
于 2013-08-24T13:35:59.690 に答える
0

ということで、もう少し詳しく説明します。これは、私がやろうとしていることのもう少し冗長なバージョンです。ここで、抽象クラスに派生クラスの適切なメソッドを指すためのインデックスのリストがあることがわかります。UI でタイプをロードしてメニュー項目を作成している場所もわかります。私はこの ItemPointer リストを使用して、ItemPointers をタグ プロパティなどに渡しています。

全体が拡張可能であることを望みます。BaseClass を継承する Class2、Class3 などを追加したい場合があります。BaseClass を使用してプラグインを作成することもできます。派生クラスには、実行可能なメソッドが少なくとも 1 つ含まれますが、多くの場合、メソッドが含まれる可能性があります。したがって、ここの 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);
            }
        }
    }
}
于 2013-08-24T13:16:29.683 に答える