7

すべて、リストを返すメソッドがあります。このメソッドは、名前に応じてSQL StoredProcedures、Views、およびFunctionsのパラメーターを返すために使用されます。私がやりたいのは、オブジェクトのリストを作成し、このリストを呼び出し元に返すことです。方法は以下の通りです

private List<T> GetInputParameters<T>(string spFunViewName)
{
    string strSql = String.Format(
        "SELECT PARAMETER_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.PARAMETERS " +
        "WHERE SPECIFIC_NAME = '{0}' AND PARAMETER_MODE = 'IN';",
        spFunViewName);
    List<string[]> paramInfoList = new List<string[]>();
    DataTable paramDt = Utilities.DTFromDB(conn, "InputParmaters", strSql);
    if (paramDt != null)
    {
        Converter<DataRow, string[]> rowConverter =
            new Converter<DataRow, string[]>(Utilities.RowColConvert);
        paramInfoList = Utilities.ConvertRowsToList<string[]>(paramDt, rowConverter);
    }
    else
        return null;

    // Build the input parameter list.
    List<T> paramList = new List<T>();
    foreach (string[] paramInfo in paramInfoList)
    {
        T t = new T(paramInfo[NAME], paramInfo[TYPE], Convert.ToInt32(paramInfo[CHARMAXLEN]));
        columnList.Add(column);
    }
    return columnList;   
}

コンストラクターを介してインスタンス化して渡すことは明らかにできませんが何をしようとしているのかは明確である必要があります。3つの追加の方法なしで私がやりたいことをする方法はありますか?Tnew

ノート。主な問題は、Tに渡すパラメーターの数が2つまたは3つになる可能性があることです。

御時間ありがとうございます。

編集:struct私が使用するのは次のとおりです

public struct Database
{
    public string name { get; set; }
    public string filename { get; set; }
    public List<Table> tables { get; set; }
    public List<StoredProcedure> sps { get; set; }
    public List<Function> funcs { get; set; }
    public List<View> views { get; set; }
    public Database(string name, string filename)
    {
        this.name = name;
        this.filename = filename;
    }
}

protected internal struct StoredProcedure
{
    public string name { get; set; }
    public List<string[]> parameters { get; set; }
    public StoredProcedure(string name, List<string[]> parameters)
    {
        this.name = name;
        this.parameters = parameters;
    }
}

protected internal struct Function
{
    public string name { get; set; }
    public string output { get; set; }
    public List<string[]> parameters { get; set; }
    public Function(string name, string output, List<string[]> parameters)
    {
        this.name = name;
        this.output = output;
        this.parameters = parameters;
    }
}

protected internal struct View
{
    public string name {get; set;} 
    public List<string[]> parameters { get; set; }
    public View(string name, List<string[]> parameters)
    {
        this.name = name;
        this.parameters = parameters;
    }
}
4

7 に答える 7

6

Activatorクラスを使用してT、パラメーターを作成して渡します。

Type type = typeof(T);
var result = (T)Activator.CreateInstance(type, new object[] { yourParameters });

コードスニペットで使用:

T t = Activator.CreateInstance(type, colInfo[NAME], colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]));
于 2012-06-21T17:47:39.503 に答える
3

他に述べたように使用するか、リフレクションオーバーヘッドを回避しActivator.CreateInstance()てデリゲートを渡す ことができます。Func<string, string, int, T>

 List<T> GetInputParameters<T>(string spFunViewName, Func<string, string, int, T> itemCreator)
 {

    ....
    List<T> paramList = new List<T>();     
    foreach (string[] paramInfo in paramInfoList)     
    {         
       T t = itemCreator(paramInfo[NAME], paramInfo[TYPE], 
            Convert.ToInt32(paramInfo[CHARMAXLEN]));         
      paramList.Add(t);     
    }     

    return columnList;    
 }
于 2012-06-21T17:53:58.870 に答える
3

私はこのテクニックを支持も損なうこともしていませんが、あなたは以下を使うことができます:

(T) Activator.CreateInstance( typeof(T), colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]) );

私はむしろ別々のファクトリメソッドを持っていると思います。

于 2012-06-21T17:48:34.777 に答える
2

明らかに、newを介してTをインスタンス化し、コンストラクターに渡すことはできません

書かれているように、いいえ。ただし、コンストラクターを使用して型のみを受け入れるように型パラメーターを制約する場合は、次のことができます。

private List<T> GetInputParameters<T>(string spFunViewName) where T : new()
{
    // your code here
}

上記の例では、次のように言うことができます。

T myItem = new T();

特定のケースでは、各ジェネリック型が共通の何かを共有することを期待しているように見えます。インターフェイスを使用して型を制約することも検討してください。

private List<T> GetInputParameters<T>(string spFunViewName) where T : new(), ISomeInterface
{
    // your code here
}

これにより、オブジェクトをインスタンス化した後、インターフェイスの任意のプロパティに値を適用できます。

T myItem = new T();

myItem.SomeProperty = somevalue;
myItem.AnotherProperty = anothervalue;

詳細については、MSDNの「型パラメーターの制約」(C#プログラミングガイド)で、ジェネリック型の制約の詳細を確認してください。

于 2012-06-21T17:58:35.967 に答える
1

ADO.NET DbProviderFactoriesを使用して、汎用データベースパラメーター(および接続とコマンドなど)を作成できます。

System.Data.Common名前空間は、特定のデータソースで動作するDbProviderFactoryインスタンスを作成するためのクラスを提供します。DbProviderFactoryインスタンスを作成し、データプロバイダーに関する情報を渡すと、DbProviderFactoryは、提供された情報に基づいて、返される正しい厳密に型指定された接続オブジェクトを決定できます。

コードで、を作成してDbProviderFactoryからを呼び出すことができますCreateParameter()

string providerName = ConfigurationManager.ConnectionStrings["YourConnectionString"].ProviderName;
DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
DbParameter parameter = factory.CreateParameter();
于 2012-06-21T17:56:58.600 に答える
1

List< DbParameter >を使用するだけで済みます

それはもう少し明白です。

于 2012-06-21T17:49:24.000 に答える
1

あなたはこれを試すことができます:

var constructor = typeof(T).GetConstructor(typeof(string), typeof(string), typeof(int));
constructor.Invoke(colInfo[NAME], colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]));
于 2012-06-21T17:50:09.673 に答える