1

次のようなテキストファイルがあります。

AssembleComponent Motor = new AssembleComponent;
AssembleComponent Shaft = new AssembleComponent;
......

Motor.cost = 100;
Motor.quantity = 100;
Shaft.cost = 10;
Shaft.quantity = 100;
......

これらのコード行をC#で実行したいので、後で計算するために、これらのMotor.cost、Motor.quantity、Shaft.cost、Shaft.quantity変数をメモリに格納します。

これを達成するために何ができますか?

4

5 に答える 5

3

代わりに XML として保存します

<?xml version="1.0" encoding="UTF-8"?>
<Components>
    <Component name="Motor" cost="100" quantity="100" />
    <Component name="Shaft" cost="10" quantity="100" />
</Components>

この定義があると仮定すると

public class AssembleComponent
{
    public decimal Cost { get; set; }
    public int Quantity { get; set; }
}

このようにロードします

var components = new Dictionary<string, AssembleComponent>();
XDocument doc = XDocument.Load(@"C:\Users\Oli\Desktop\components.xml");
foreach (XElement el in doc.Root.Descendants()) {
    string name = el.Attribute("name").Value;
    decimal cost = Decimal.Parse(el.Attribute("cost").Value);
    int quantity = Int32.Parse(el.Attribute("quantity").Value);
    components.Add(name, new AssembleComponent{ 
                             Cost = cost, Quantity = quantity
                         });
}

その後、このようにコンポーネントにアクセスできます

AssembleComponent motor = components["Motor"];
AssembleComponent shaft = components["Shaft"];

注: 実行時にコンパイラを呼び出して変数名を動的に作成することは、有用なことを行うためにコンパイル時 (または必要に応じて設計時) にそれらを知る必要があるため、あまり役に立ちません。したがって、コンポーネントを辞書に追加しました。これは、「変数」を動的に作成する良い方法です。

于 2012-10-30T16:37:29.423 に答える
2

Microsoft.CSharp.CSharpCodeProviderオンザフライでコードをコンパイルするために使用できます。

具体的には、CompileAssemblyFromFileを見てください。

于 2012-10-30T16:13:38.673 に答える
2

データだけの場合は、フラット テキスト ファイルを使用せず、代わりに XML を使用します。

XML をオブジェクトに逆シリアル化し、それらに対して必要なアクションを実行できます。

于 2012-10-30T16:15:39.327 に答える
2

ここに私が過去に使用したいくつかのコードがあります。これは、特定のニーズに合わせて調整する必要があるかもしれませんが、ほとんどのことを行います。簡単に言えば、次のことを行います。

  • 一時的な名前空間とその名前空間に public static メソッドを作成します。
  • コードをメモリ内アセンブリにコンパイルします。
  • コンパイルされたメソッドを抽出し、デリゲートに変換します。
  • デリゲートを実行します。

その時点で、通常の静的メソッドを実行するのと同じように、後で使用するために結果をメモリに格納したい場合は、それがどのように機能するかを理解する必要があります。

public void CompileAndExecute(string CodeBody)
{
    // Create the compile unit
    CodeCompileUnit ccu = CreateCode(CodeBody);

    // Compile the code 
    CompilerParameters comp_params = new CompilerParameters();
    comp_params.GenerateExecutable = false;
    comp_params.GenerateInMemory = true;
    comp_params.TreatWarningsAsErrors = true;
    comp_results = code_provider.CompileAssemblyFromDom(comp_params, ccu);

    // CHECK COMPILATION RESULTS
    if (!comp_results.Errors.HasErrors)
    {
        Type output_class_type = comp_results.CompiledAssembly.GetType("TestNamespace.TestClass");

        if (output_class_type != null)    
        {    
            MethodInfo compiled_method = output_class_type.GetMethod("TestMethod", BindingFlags.Static | BindingFlags.Public);    
            if (compiled_method != null)    
            {    
                Delgate created_delegate = Delegate.CreateDelegate(typeof(System.Windows.Forms.MethodInvoker), compiled_method);
                if (created_delegate != null)
                {
                    // Run the code
                    created_delegate.DynamicInvoke();
                }
            }
        }
    }
    else
    {
        foreach (CompilerError error in comp_results.Errors)
        {
            // report the error
        }
    }
}

public CodeCompileUnit CreateCode(string CodeBody)
{
    CodeNamespace code_namespace = new CodeNamespace("TestNamespace");

    // add the class to the namespace, add using statements
    CodeTypeDeclaration code_class = new CodeTypeDeclaration("TestClass");
    code_namespace.Types.Add(code_class);
    code_namespace.Imports.Add(new CodeNamespaceImport("System"));

    // set function details
    CodeMemberMethod method = new CodeMemberMethod();
    method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
    method.ReturnType = new CodeTypeReference(typeof(void));
    method.Name = "TestMethod";

    // add the user typed code
    method.Statements.Add(new CodeSnippetExpression(CodeBody));

    // add the method to the class
    code_class.Members.Add(method);

    // create a CodeCompileUnit to pass to our compiler
    CodeCompileUnit ccu = new CodeCompileUnit();
    ccu.Namespaces.Add(code_namespace);

    return ccu;
}
于 2012-10-30T16:44:24.823 に答える
0

主なオプションは 2 つあります。

  1. テキストを有効な C# コードになるまで展開し、コンパイルして実行します
  2. それを解析し、自分で実行します (つまり、解釈します)。
于 2012-10-30T16:15:34.820 に答える