0

一般的な形式のテキストファイルがあります。

ThreadID, MethodName, [Param1 | Param2 | ... ]

そして、私は次のようなユーティリティクラスを持っています:

public static class Util
{
    public static List<double> Foo(List<double> Source, double Scale)
    {
        List<double> l = new List<double>(Source);
        for (int i = 0; i < l.Count; i++)
        {
            l[i] = l[i] * Scale;
        }
        return l;
    }

    public static void Fud(List<double> Source, string Name)
    {
        //... Chart Series
    }
    public static bool Fee(CustomClass MyClass, double Limit1, int Limit2)
    {
        //... Test MyClass values against input limits
        return true; // false;
    }
}

そのため、テキストファイルからメソッド名を指定し、ケース内のメソッドに引数を解析して渡すスイッチ/ケースを使用していました。sudoコードは、次のような効果があります。

    static void Main(string[] args)
    {
        List<string> TextFile;
        List<double>[] Register = new List<double>[3];   //lists containing data that is moved, mutated and converted to CustomClass
        CustomClass MyClass = new CustomClass();
        bool Passed = false;

        foreach (var line in TextFile)
        {
            string methodName = Util.ParseMethod(line);          //parsed from file
            string param1, param2, param3, param4 = Util.ParseParams(line);          //parsed from file
            switch (methodName)
            {
                case "Foo":
                    Register[param1] = Util.Foo(Register[param2], param3);
                    break;

                case "Fud":
                    Util.Fud(Register[param1], param3);
                    break;

                case "Fee":
                    Passed = Util.Foo(MyClass, param1, param2);
                    break;
            }
        }
    }

ロジックを分割するのが嫌いで、新しいユーティリティメソッドを開発するたびに、別のcaseステートメントを手動で追加する必要があります。設計時のエラー(文字列/更新のタイプミス)は通常、実行時にのみキャッチされるため、caseステートメントの保守が困難になりました。

これをすべてファクトリアーキテクチャに変換しようとしましたが、さまざまなメソッド定義に対応できないようです。Utilityクラスを廃止し、ファクトリインターフェイスを使用して独自のクラスで各メソッドを定義したいと考えていました。

public interface IRecipe
{
    string GetFactoryKey();
    string SerializeArgs(object[] args);
    object[] DeserializeArgs(string args);
    ??? DoWork(???);
}

問題は、ユーティリティクラスの各メソッドがどれほど異なっていたか、インターフェイスで適切に定義する方法が見つからないことです。私が望む最終結果は、foreachループのスイッチをジェネリックコードに置き換えることができ、すべての本質的なロジック、解析、メソッド定義、エラーチェック、および検証が、メソッド呼び出し元ではなく、ファクトリインターフェイスを実装する各クラスで定義されることです。 。私が何をしたいのかわからないので、私はグーグルするものが不足しています。

4

2 に答える 2

0

DoWorkメソッドが単一の文字列引数(コンマで区切られたパラメーター)を取り、必要に応じて分割した場合はどうなりますか?その後も、シンプルなインターフェイスを使用して、詳細を各レシピに任せることができます。

もう1つのオプションは、パラメーターとしての文字列配列です。これは、作業を新しいスレッドにスピンオフする方法と似ています(呼び出すメソッドとそのパラメーターを含む配列を指定します)。

于 2013-01-03T19:49:14.260 に答える
0

私はそれを理解したと思います...これはこれまでの私の完全な概念実証です。まだ少し醜いですが、少なくとも各ファクトリクラスにその醜さをカプセル化しています。つまり、Mainの呼び出し元は、ループで簡単に使用できるように非常に一般的なままでいることができます。実際の実装を行うときに、これをもう少しリファクタリングします。

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            List<double>[] Reg = new List<double>[2]; for (int i = 0; i < Reg.Length; i++) { Reg[i] = new List<double>(); }

            for (int i = 0; i < 100; i++)
            { Reg[1].Add(1.0); }            //Dummy data

            var obj = ClassFactory.CreateStep("AmplifySignal");
            object[] Args = obj.DeserializeProperties(" ");
            Args[0] = Reg;
            dynamic result = obj.Run(Args);

            if (result != null)
            { Thread.Sleep(0); }    //breakpoint

            Console.ReadKey();
        }
    }

    internal static class ClassFactory
    {
        private static readonly IDictionary<String, Type> _recipe_instructions;

        static ClassFactory() { _recipe_instructions = MapIFactory(); }

        private static IDictionary<string, Type> MapIFactory()
        {
            // Get the assembly that contains this code
            Assembly asm = Assembly.GetExecutingAssembly();

            // Get a list of all the types in the assembly
            Type[] allTypes = asm.GetTypes();

            var d = new Dictionary<string, Type>();
            foreach (var type in allTypes)
            {
                if (type.IsClass && !type.IsAbstract && type.GetInterface(typeof(IFactory).ToString()) != null)
                {
                    // Create a temporary instance of that class...
                    object inst = asm.CreateInstance(type.FullName, true, BindingFlags.CreateInstance, null, null, null, null);
                    if (inst != null)
                    {
                        // And generate the product classes key
                        IFactory mapKey = (IFactory)inst;
                        object key = mapKey.GetFactoryKey();
                        inst = null;

                        //Add the results to a Dictionary with the Name as a key and the Type as the value
                        d.Add((string)key, type);
                    }
                }
            }
            return d;
        }

        internal static IFactory CreateStep(String key)
        {
            Type type;
            if (_recipe_instructions.TryGetValue(key, out type))
            { return (IFactory)Activator.CreateInstance(type); }
            throw new ArgumentException(String.Format("Unable to locate key: {0}", key));
        }
    }

    public interface IFactory
    {
        string GetFactoryKey();
        string SerializeProperties();
        object[] DeserializeProperties(string args);
        dynamic Run(params object[] args);
    }

    public class AmplifySignal : IFactory
    {
        public string GetFactoryKey()
        { return MethodBase.GetCurrentMethod().DeclaringType.Name; }
        public object[] DeserializeProperties(string args)
        { return new object[] { null, (int)1, (double)2.1 }; }
        public string SerializeProperties()
        { return " 1 | 2.1 "; }

        public dynamic Run(params object[] args)
        {
            // Build Inputs
            List<double>[] registers = (List<double>[])args[0];
            List<double> waveform = (List<double>)registers[(int)args[1]];
            double factor = (double)args[2];

            // Do Work
            double[] Result = waveform.ToArray();      //Localize and Deep Copy
            for (int i = 0; i < Result.Length; i++)
            { Result[i] *= factor; }
            List<double> result = Result.ToList();    //breakpoint

            // Write Result
            return result;
        }
    }
}

私がここで本当に犠牲的なことをしたことがあり、同じことを達成するためのより良い方法があるなら、どうしても私は提案を受け入れます。フィードバックを可能にするための回答としてこれを受け入れる前に、1日か2日待ちます。

于 2013-01-03T23:23:22.950 に答える