بناء جملة C# للإعلان عن متغير من النوع العام المجرد

StackOverflow https://stackoverflow.com/questions/822326

  •  03-07-2019
  •  | 
  •  

سؤال

لدي فئة محددة على النحو التالي؛

public abstract class Repository<TEntity, TDataContext> : DisposableBaseClass
   where TEntity : class
   where TDataContext : DataContext, new()
{...contains Linq to SQL related functionality

في الفئة الفرعية الملموسة، أحدد الأنواع على هذا النحو؛

public class ConcreteRepo : Repository<LSTableClass, LSDataContext>

في المستوى التالي، لدي كائنات أعمال تحتوي على كائن المستودع كمتغير خاص.

كان هذا جيدًا؛

private ConcreteRepo _repository;

ومع ذلك، قمت بعد ذلك بإعادة هيكلة ذلك إلى فئة أصل لجميع كائنات الأعمال - تحتفظ هذه الفئة الأصلية بالمستودع/تنفذ نمط التخلص للتخلص من المستودع وما إلى ذلك.

مشكلتي هي أنني لا أستطيع الحصول على الصيغة الصحيحة لإعلان المتغير.

أقرب ما جئت هو؛

protected Repository<Object, DataContext> _repository;

ولكن هذا يعطي خطأ الترجمة:

"الخطأ 1 يجب أن يكون "System.Data.Linq.DataContext" نوعًا غير مجرد مع مُنشئ عام بدون معلمات لاستخدامه كمعلمة "TDataContext" في النوع العام أو الأسلوب "....المستودع"... "

لقد جربت أشياء أخرى مختلفة ولكن واجهت مشاكل أخرى.

في كائن طبقة الأعمال الذي يرث هذه الفئة المجردة، أقوم بإنشاء واستخدام متغير _repository مع طاقم الممثلين؛

(Repository<LSTableClass, LSDataContext>)_repository = new ConcreteRepo();
  • وأعتقد أن هذا سيكون جيدًا، على افتراض أنني أستطيع الحصول على هذا الإقرار بشكل صحيح من أحد الوالدين.

إذا لم أتمكن من تشغيل هذا، فلا بد لي من الإعلان عن _repository في كل كائن عمل، مع تفاصيل النوع الكاملة/الملموسة، وتنفيذ نمط التخلص في كل واحد لتوضيحه.ليست نهاية العالم، لكني لا أرغب في ذلك.

هل كانت مفيدة؟

المحلول

إذا فهمت مشكلتك بشكل صحيح، فأنت بحاجة إلى إضافة معلمة عامة ثالثة، نوع المستودع، الذي يقتصر على أن يكون سليلًا Repository مع أنواع الوسيطة المناسبة.

لتوضيح ذلك أكثر:

public abstract class Repository<TEntity,TDataContext>
    where TEntity : class
    where TDataContext : DataContext, new() {}

public abstract class BusinessObject<TEntity,TDataContext,TRepository>
    where TEntity : class
    where TDataContext : DataContext, new()
    where TRepository : Repository<TEntity,TDataContext>
{
    TRepository _repository;
}

public class ConcreteObject : BusinessObject<LSTableClass,LSDataContext,ConcreteRepo>
{ // ...

أعلم أنها ربما ليست مضغوطة كما تريد، ولكن ما هو مطلوب لتقليل ذلك بشكل فعال مع الاحتفاظ بالكتابة القوية، هو الأنواع العامة ذات الترتيب الأعلى (تسمى فئات النوع في هاسكل):طريقة للإشارة إلى أن معلمات النوع هي في حد ذاتها عامة، ويمكن أن تأخذ معلمات النوع.

نصائح أخرى

إعلانك

protected Repository<Object, DataContext> _repository;

لم ينجح بسبب القيد الذي وضعته عليه:

...    
where TDataContext : DataContext, new()

على وجه التحديد new() جزء.

أعتقد أنك تريد "حقن" كائن يرضي واجهتك العامة.

شيئان:

  • لا يمكنك التحويل بين Repository<Object, DataContext> و Repository<LSTableClass, LSDataContext>.ليس مع C # 3.وهذا ما يسمى Contravariance/Covariance ولن يكون متاحًا حتى C# 4.في C#3، هناك نوعان مختلفان تمامًا.

  • إذا كنت تريد تخزين عضو عام داخل فئة ما، فيجب أن تكون وسيطات النوع إما أنواعًا محددة، أو يجب الإعلان عنها كمعلمات نوع في إعلان الفئة الأصل (مما يجعل الذي - التي نوعي).

خيارات:

  • استخدم وسيطات النوع العامة في صفك الأصلي.
  • قم بإزالة القيد الجديد () من إعلان الفصل الدراسي الخاص بك.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top