读取配方以控制数据处理步骤

时间:2013-01-03 19:43:27

标签: c#

我有一般格式的文本文件:

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;
    }
}

所以我使用了一个switch / case,它给出了文本文件中的方法名称,然后解析并传递参数给案例中的方法。 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语句。案例陈述变得难以维护,因为设计时错误(字符串/更新中的拼写错误)通常只在运行时被捕获。

我尝试将此全部转换为Factory架构,但我似乎无法适应不同的方法定义。我希望废除Utility类,并使用工厂接口在其自己的类中定义每个方法。

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

问题是因为实用程序类中的每个方法有多么不同,我找不到在接口中正确定义它的方法。我想要的最终结果是我可以用通用代码替换foreach循环中的开关,并且在实现工厂接口而不是方法调用者的每个类中定义所有细节逻辑,解析,方法定义,错误检查和验证。我已经用完了谷歌的东西,因为我不知道我想做什么甚至被叫。

1 个答案:

答案 0 :(得分: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;
        }
    }
}

如果我在这里做了一些真正亵渎神灵的事情,并且有更好的方法来完成同样的事情,那么无论如何我都愿意接受建议。在接受这个作为答案以允许任何反馈之前,我会等待一两天。