7

以下に示すように、リフレクションを使用して動的にクラスを構築できますか? メソッドはなく、パブリック変数だけで、カスタム属性を持つものもあります。

.Emit メソッドが必要ですか (私が見たところ、「Emit」は少し難しいように見えます)。

www.FileHelpers.netのソフトウェアを使用していますが、クラスが必要です。すべてのファイル定義はデータベース テーブルにあり、すべてをより動的にしたいと考えています (つまり、ファイルに新しい列が表示されたときにコードを変更しません)。

[FileHelpers.DelimitedRecord(",")]
public class FileRow
{
    [FileHelpers.FieldQuoted('"', QuoteMode.OptionalForBoth)] 
    public string Borrower_First_Name;
    [FileHelpers.FieldQuoted('"', QuoteMode.OptionalForBoth)] 
    public string Borrower_Last_Name;
    public string Borrower_Email;
}

更新 1: 以下の Vlad の回答に基づいて、DLL を参照する必要がありました。

    // need to reference the FileHelpers.dll from our own .exe directory 
    string diskFilenameFileHelpersDLL = 
        System.IO.Path.GetDirectoryName(
           System.Reflection.Assembly.GetExecutingAssembly().Location) + 
           @"\FileHelpers.dll";

更新 2: また、Vlad が提案したことを実行した後、これが FileHelper を呼び出して結果をループする方法です。おそらくデータをリストに転送します。

    Assembly assembly = compiledResult.CompiledAssembly;

    // Simple Data Test 
    lineContents = "John,Doe,jd123456@yahoo.com";
    FileHelperEngine engine = new FileHelperEngine(assembly.GetType("FileRow"));
    // FileRow[] FileRowArray = (FileRow[])engine.ReadString(lineContents);
    Object[] FileRowArray = engine.ReadString(lineContents);
    Object myObject = FileRowArray[0];  // only 1 row of data in this example 

    // Get the type handle of a specified class.
    Type myType = assembly.GetType("FileRow");
    // Get the fields of the specified class.
    FieldInfo[] myField = myType.GetFields();

    Console.WriteLine("\nDisplaying fields values:\n");
    for (int i = 0; i < myField.Length; i++)
    {
        Object objTest = myField.GetValue(i);

        string tempName = myField[i].Name;
        Object objTempValue = myField[i].GetValue(myObject);
        string tempValue = System.Convert.ToString(objTempValue);

        Console.WriteLine("The value of {0} is: {1}",
                            tempName, tempValue);

    }
4

2 に答える 2

3

コードを文字列としてデータベースに保存している場合、アセンブリを作成するために次のように実行できます。

属性の名前空間がないため、属性をコメントアウトした理由。名前空間があり、コンパイルするにはそれをコードに追加する必要があると想定しています。

コードはLINQPadで機能するため、コピーして貼り付けるだけです。

using System;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

void Main()
{
    StringBuilder dc = new StringBuilder(512);
    dc.Append("public class FileRow");
    dc.Append("{");
    //dc.Append("[FileHelpers.FieldQuoted('\"', QuoteMode.OptionalForBoth)]");
    dc.Append("public string Borrower_First_Name;");
    //dc.Append("[FileHelpers.FieldQuoted('\"', QuoteMode.OptionalForBoth)]");
    dc.Append("public string Borrower_Last_Name;");
    dc.Append("public string Borrower_Email;");
    dc.Append("}");

    CompilerResults compiledResult = CompileScript(dc.ToString());

    if (compiledResult.Errors.HasErrors)
    {
        Console.WriteLine (compiledResult.Errors[0].ErrorText);
        throw new InvalidOperationException("Invalid Expression syntax");
    }

    Assembly assembly = compiledResult.CompiledAssembly;

    // This is just for testing purposes.
    FieldInfo field = assembly.GetType("FileRow").GetField("Borrower_First_Name");          
    Console.WriteLine (field.Name);         
    Console.WriteLine (field.FieldType);
}

public static CompilerResults CompileScript(string source) 
{ 
    CompilerParameters parms = new CompilerParameters(); 

    parms.GenerateExecutable = false; 
    parms.GenerateInMemory = true; 
    parms.IncludeDebugInformation = false; 

    CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp"); 

    return compiler.CompileAssemblyFromSource(parms, source); 
} 
于 2012-02-23T14:30:55.027 に答える
2

CodeDOM を使用してクラスを動的に生成することもできます。詳細については、次を参照してください。

http://msdn.microsoft.com/en-us/library/ms404245.aspx

于 2012-02-23T14:01:34.307 に答える