C # Generics Instantiation

كل شيء ، لدي طريقة تقوم بإرجاع قائمة. يتم استخدام هذه الطريقة لإرجاع معلمات SQL StoredProcedures ووظائف ووظائف استناداً إلى الاسم. ما أريد القيام به هو إنشاء قائمة من الكائنات وإرجاع هذه القائمة إلى المتصل. الطريقة أدناه

private List GetInputParameters(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 paramInfoList = new List();
    DataTable paramDt = Utilities.DTFromDB(conn, "InputParmaters", strSql);
    if (paramDt != null)
    {
        Converter rowConverter =
            new Converter(Utilities.RowColConvert);
        paramInfoList = Utilities.ConvertRowsToList(paramDt, rowConverter);
    }
    else
        return null;

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

لا أستطيع بوضوح إنشاء شفرة T عبر جديد ثم تمريرها إلى المُنشئ ، ولكن يجب أن يكون واضحًا ما أحاول القيام به. هل هناك طريقة لفعل ما أريد من خلال ثلاث طرق إضافية؟

ملحوظة. تكمن المشكلة الرئيسية في أن عدد المعلمات التي أمررها إلى T يمكن أن يكون إما ثلاثة أو ثلاثة.

شكرا على وقتك.

تحرير: struct s I s هي كما يلي

public struct Database
{
    public string name { get; set; }
    public string filename { get; set; }
    public List<table> tables { get; set; }
    public List sps { get; set; }
    public List funcs { get; set; }
    public List 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 parameters { get; set; }
    public StoredProcedure(string name, List parameters)
    {
        this.name = name;
        this.parameters = parameters;
    }
}

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

protected internal struct View
{
    public string name {get; set;} 
    public List parameters { get; set; }
    public View(string name, List parameters)
    {
        this.name = name;
        this.parameters = parameters;
    }
}
0
أفترض "InputParmaters" هو خطأ مطبعي؟
وأضاف المؤلف comecme, مصدر
Jon Skeet ، إنها في الواقع بنية . أحاول بناء بنية شجرة قابلة لإعادة الاستخدام لإظهار قواعد البيانات والجداول وما إلى ذلك ، ولكنني أريد أيضًا أن أكون قادرًا على استخدام المعلومات التي تم الحصول عليها من هذا الإجراء مرة أخرى - لذلك أستخدم نمطًا مفردًا مع struct StoredProcedure ، struct Function etc. شكرا.
وأضاف المؤلف MoonKnight, مصدر
JonSkeet ، من حقك ، لست بحاجة إلى القيام بذلك - الحلقة غير متكررة. ولكن لا يزال لدي مشكلة أن منشئ T يمكن أن يكون لديك معلمتين أو ثلاثة. سأقرأ هذا المقال شكرا للإشارة. آمل أن تسير مبيعات الكتب الجديدة بشكل جيد ...
وأضاف المؤلف MoonKnight, مصدر
JonSkeet ، شكرًا على وقتك هنا. T في هذه الحالة سيكون إما struct s أعلاه (إما StoredProcedure أو Function أو View </القانون>). لماذا في هذه الحالة يجب أن يكونوا فصولا - فكرت في رؤية ما أقوم بإنشاء كائن قاعدة البيانات فقط بمجرد أن يكون ذلك على ما يرام. ومع ذلك ، أستطيع أن أرى أن هذا يمكن أن يحمل معلومات عادلة ...
وأضاف المؤلف MoonKnight, مصدر
@ جون سكيت ، آسف ، هذا لم يكن واضحا. أريد فقط أن أقوم بهذه العملية مرة واحدة ، لذلك لديّ فصل يبني معلومات الشجرة وأحتفظ به - أعيد البناء فقط إذا قمت بالتخلص من المفرد. ضمن هذا الفصل لدي هياكل تحدد السمات (الجدول ، أعمدتها ، sps ، وظائفها ، وعرضها (مع معلماتها)). وظائف لها معلمات المدخلات والمخرجات ، وجهات النظر و sps لا ...
وأضاف المؤلف MoonKnight, مصدر
comecme لا ، ليس كذلك.
وأضاف المؤلف MoonKnight, مصدر
المشكلة التي أواجهها هي أنني قضيت سنوات عديدة في كتابة FORTRAN لدرجة أنني غالباً ما أجد صعوبة في رؤية ما هو أفضل منهج OOP ...
وأضاف المؤلف MoonKnight, مصدر
Killercam: ولكن المعلمة ليست إجراء مخزن ، ولا هي وظيفة. لماذا لا يكون لديك نوع واحد لتمثيل المعلمات ، ثم نستخدم ذلك مع تكوين للإجراءات المخزنة وما إلى ذلك. ليس من الواضح أين يأتي نمط المفرد ، لكنني د تجنب ذلك بشدة إذا كنت أنت ... وفكرة وجود هيكل مفرد لا معنى للبدء :(
وأضاف المؤلف Jon Skeet, مصدر
Killercam: ولكنك لم تظهر ما تريده T (الذي يمثل معلمة بقدر ما أستطيع رؤيته). أوه ، وتلك البنى تبدو وكأنها يجب أن تكون حقا.
وأضاف المؤلف Jon Skeet, مصدر
Killercam: ولكنك تقوم بإنشاء مثيل T لكل معلمة ، وهو ليس صحيحًا إذا كانت T هي StoredProcedure أو Function ، أليس كذلك؟ ولماذا يجب أن تكون هذه الفئات - اقرأ msdn.microsoft.com/en-us /library/ms229017.aspx
وأضاف المؤلف Jon Skeet, مصدر
ما هو نوع T المحتمل أن يكون هنا؟
وأضاف المؤلف Jon Skeet, مصدر
Killercam: لا أرى أن لديك مشكلة على الإطلاق. يُقصد من طريقتك إرجاع المعلمات ، لذلك يجب عليك القيام بذلك. يمكن للمتصل بناء StoredProcedure/Function/أيا كان. حاول تجنب القيام بالكثير في طريقة واحدة.
وأضاف المؤلف Jon Skeet, مصدر
لمتابعة جون سكيت ، يمكنك وضع قيد عام بحيث تدعم T دائمًا مُنشئًا ترغب في استخدامه. أو ، إذا كان دائمًا نفس البنية ، فاجعلها list فقط
وأضاف المؤلف Aphelion, مصدر

7 إجابة

0
وأضاف

You could just use List<DbParameter>

هذا هو أكثر وضوحا بعض الشيء.

0
وأضاف

You can use Activator.CreateInstance() as other mentioned or pass a delegate Func avoiding the reflection overhead .

 List GetInputParameters(string spFunViewName, Func itemCreator)
 {

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

    return columnList;    
 }
0
وأضاف

يمكنك تجربة هذا:

var constructor = typeof(T).GetConstructor(typeof(string), typeof(string), typeof(int));
constructor.Invoke(colInfo[NAME], colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]));
0
وأضاف

استخدم فئة 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]));
0
وأضاف
حسنا لقد فعلت. شكرا مرة أخرى على وقتك...
وأضاف المؤلف MoonKnight, مصدر
أسف على هذا. هذا يبدو جديدا بالنسبة لي. هل تقول لتغليف الهياكل المتعددة في فصل واحد واستخدام ذلك؟
وأضاف المؤلف MoonKnight, مصدر
في هذه المرحلة ، لست متأكدًا من السبب؟ هل يمكن أن تضحك لي؟ لدي ثلاثة أنواع ، sps ، وظائف وجهات النظر. سحب هذه لها معلمات الإدخال فقط (SP وجهات النظر) ، وظائف لها على حد سواء ...
وأضاف المؤلف MoonKnight, مصدر
مذهلة ، لم أكن أعرف عن هذا على الإطلاق ، شكرا جزيلا على وقتك ...
وأضاف المؤلف MoonKnight, مصدر
لا توجد مشكلة. ومع ذلك كما كتب آخرون أنه من الأفضل تجنب ذلك واستخدام appproach مصممة مختلفة.
وأضاف المؤلف Aphelion, مصدر
حسنا ، لقد قرأت الآن أنك تستخدم البنى. ومع ذلك ، يمكنك البحث عن أو إنشاء فئة مميزة مع المُنشئ ووضعها كقيد على T. ثم لن تحتاج إلى استخدام المنشط.
وأضاف المؤلف Aphelion, مصدر
من الأفضل نشر مثال على نوع البنى التي لديك في السؤال ؛). في الوقت الحالي لا يمكنني التأكد.
وأضاف المؤلف Aphelion, مصدر

أنا لا أؤيد هذا الأسلوب أو أخلعه ، ولكن يمكنك استخدام:

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

أعتقد أنني سأفضل أساليب مصنع منفصلة.

0
وأضاف

لا يمكنني بوضوح إنشاء T عن طريق تمريره إلى المُنشئ

كما هو مكتوب ، لا ؛ ومع ذلك ، يمكنك أن إذا قمت بتقييد معلمة النوع الخاص بك لقبول الأنواع مع المنشئات فقط:

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

في المثال أعلاه ، ستتمكن من قول:

T myItem = new T();

في حالتك المحددة ، يبدو أنك تتوقع أن تشترك كل أنواع عامة في شيء مشترك. فكر أيضًا في تقييد النوع بواجهة:

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

يسمح لك ذلك ، بعد قيامك بتشكيل كائن ، تطبيق القيم على أي خصائص على الواجهة:

T myItem = new T();

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

لمزيد من المعلومات ، راجع القيود على معلمات النوع ( C# Programming Guide) على MSDN لمزيد من المعلومات حول قيود النوع العامة.

0
وأضاف
هذا تم فعله أو انجازه...
وأضاف المؤلف MoonKnight, مصدر
أنا أحب هذا كثيرا! ولكن لا يعني حقيقة أن الأشياء الموجودة في هياكلي الثلاثة مختلفة لا أستطيع استخدام واجهة كما هو كل شيء أو لا شيء؟
وأضاف المؤلف MoonKnight, مصدر
من الناحية المثالية ، في هذه الحالة ، سيكون كل من البنى (أو الفصول) قادراً على تنفيذ (أو ورث) نفس الواجهة أو الطبقة الأساسية ، إن لم يكن أي شيء آخر ، مجرد شيء بطريقة مصنع. هل ستتمكن من تحديث سؤالك ليشمل البنيات الفعلية؟
وأضاف المؤلف Steve Konves, مصدر
وأضاف المؤلف Steve Konves, مصدر