سؤال

لقد كنت أحاول إنشاء فئة أساسية بسيطة تغلف بعض الاتفاقيات الخاصة بي للوصول إلى قاعدة البيانات. أقوم عمومًا بإنشاء sproc اسمه "products_retrieve_product" لتحديد منتج يعتمد على منتج. أرغب في إرجاع طريقة "استرداد" الفئة الأساسية إلى النوع الذي تقوم به الفئة المشتقة في تعريفه. هل ما أحاول تحقيقه ممكنًا مع الأدوية الجيلية؟

public class MyBaseClass <T>
{
    private string _className;

    public MyBaseClass ()
    {
        _className = this.GetType().Name;
    }

    public virtual T Retrieve(int ID)
    {
        Database db = DatabaseFactory.CreateDatabase();
        DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", _className));
        db.AddInParameter(dbCommand, String.Format("@{0}ID", _className), DbType.Int32, ID);

        using (IDataReader dr = db.ExecuteReader(dbCommand))
        {
            if (dr.Read())
            {
                BOLoader.LoadDataToProps(this, dr);
            }
        }
        return (T)this;
    }
}
هل كانت مفيدة؟

المحلول

أعتقد أنك تريد أن تفعل شيئًا كهذا:

class MyBaseClass<T> where T : MyBaseClass<T>, new()
{
    public T Retrieve()
    {
        return new T();
    }
}

class Foo : MyBaseClass<Foo>
{
}

class Program
{
    public static void Main()
    {
        Foo f = new Foo();
        Foo f2 = f.Retrieve();
        Console.WriteLine(f2.ToString());
    }
}

عند تشغيل هذا البرنامج ، تتم طباعة اسم نوع FOO على سطر الأوامر. من الواضح أن هذا مثال مفتعل ، ولكن ربما يمكنك القيام بشيء أكثر فائدة عند التحميل من قاعدة بيانات في MyBaseClass.Retrieve().

المفتاح هو إضافة قيد على T بحيث يجب أن يكون مثيلًا للفصل نفسه. وبهذه الطريقة يمكنك تحديد الفئة الفرعية كنوع عام عند التصنيف الفرعي MyBaseClass<T>.

لست متأكدًا تمامًا مما إذا كانت هذه فكرة جيدة أم لا ، ولكن يبدو أنه يمكن القيام بذلك.

نصائح أخرى

بالتأكيد. في مثالك ، إذا أردت أن تعيد فئة Foo الخاصة بي عند استدعاء (...):

public class Foo : MyBaseClass<Bar>{}

حسنًا ، نحن نستخدم التفكير للحصول على اسم الفصل. لا شك أن Boloader يستخدم الانعكاس لتحميل بعض الخصائص. لماذا لا تلتزم تمامًا بالتفكير؟

لا يهتم Boloader بهذه اللعبة من "نوع العودة". لماذا ينبغي لنا؟

public static class MyBaseClassExtender
{
    public static void Retrieve(this MyBaseClass entity, int ID)
    {
        string className = entity.GetType().Name;
        Database db = DatabaseFactory.CreateDatabase();
        DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", className));
        db.AddInParameter(dbCommand, String.Format("@{0}ID", className), DbType.Int32, ID);

        using (IDataReader dr = db.ExecuteReader(dbCommand))
        {
            if (dr.Read())
            {
                BOLoader.LoadDataToProps(this, dr);
            }
        }
    }
}

ثم تقول فقط:

Foo myFoo = new Foo();
myFoo.Retrieve(2);

لا ، هذا ليس كذلك ، لأن ما تحتاجه حقًا أن تكون قادرًا على فعله هو شيء من هذا القبيل في تعريف الفصل:

public class MyBaseClass<T> : T

وهو أمر غير ممكن حاليًا مع الأدوية الجيرية.

ما عليك القيام به هو فصل المصنع عن ما ينتج عنه المصنع (تحتاج إلى فئة منفصلة ستبني T وبعد ذلك يجب أن توفر أساليب مساعد للعمل على طرق التمديد).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top