تجاوز المنشئ الافتراضي للفئة الجزئية بفئة جزئية أخرى

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

سؤال

لا أعتقد أن هذا ممكن، ولكن إذا كان الأمر كذلك فأنا بحاجة إليه :)

لدي ملف وكيل تم إنشاؤه تلقائيًا من أداة سطر الأوامر wsdl.exe بواسطة Visual Studio 2008.

إخراج الوكيل هو فئات جزئية.أريد تجاوز المنشئ الافتراضي الذي تم إنشاؤه.أفضل عدم تعديل الكود لأنه يتم إنشاؤه تلقائيًا.

لقد حاولت إنشاء فئة جزئية أخرى وإعادة تعريف المُنشئ الافتراضي، لكن ذلك لم ينجح.حاولت بعد ذلك استخدام التجاوز والكلمات الرئيسية الجديدة، لكن ذلك لم ينجح.

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

هل هناك أي أفكار أو طرق عمل أو حيل؟

//Auto-generated class
namespace MyNamespace {
   public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {
      public MyWebService() {
         string myString = "auto-generated constructor";
         //other code...
      }
   }
}

//Manually created class in order to override the default constructor
namespace MyNamespace {
   public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {
      public override MyWebService() { //this doesn't work
         string myString = "overridden constructor";
         //other code...
      }
   }
}
هل كانت مفيدة؟

المحلول

وهذا غير ممكن. فئات جزئية هي في الأساس أجزاء من نفس الفئة. يمكن تعريف أي طريقة مرتين أو تجاوز، وهذا يشمل المنشئ.

هل يمكن استدعاء أسلوب في منشئ، وإلا تنفيذه في ملف الجزء الآخر.

نصائح أخرى

وكان لي prolem مماثل، مع بلدي الشفرة التي تم إنشاؤها يتم إنشاؤه بواسطة ملف DBML (أنا usng الطبقات ينق إلى SQL).

في الفئة التي تم إنشاؤها يدعو فراغ جزئي دعا OnCreated () في نهاية المنشئ.

وقصة قصيرة طويلة، إذا كنت تريد أن تبقي الاشياء منشئ المهم الفئة التي تم إنشاؤها يفعل لك (والذي ربما يجب عليك القيام به)، ثم في الصف الجزئية الخاصة بك إنشاء ما يلي:

partial void OnCreated()
{
    // Do the extra stuff here;
}

هممم ، أعتقد أن الحل الأنيق هو ما يلي:

//* AutogenCls.cs file
//* Let say the file is auto-generated ==> it will be overridden each time when
//* auto-generation will be triggered.
//*
//* Auto-generated class, let say via xsd.exe
//*
partial class AutogenCls
{
    public AutogenCls(...)
    {
    }
}



//* AutogenCls_Cunstomization.cs file
//* The file keeps customization code completely separated from 
//* auto-generated AutogenCls.cs file.
//*
partial class AutogenCls
{
    //* The following line ensures execution at the construction time
    MyCustomization m_MyCustomizationInstance = new MyCustomization ();

    //* The following inner&private implementation class implements customization.
    class MyCustomization
    {
        MyCustomization ()
        {
            //* IMPLEMENT HERE WHATEVER YOU WANT TO EXECUTE DURING CONSTRUCTION TIME
        }
    }
}

هذا النهج له بعض العيوب (مثل كل شيء):

  1. ليس من الواضح متى سيتم تنفيذ مُنشئ الطبقة الداخلية MyCustomization أثناء إجراء الإنشاء الكامل لفئة AutogenCls.

  2. إذا كان من الضروري تنفيذ واجهة IDiposable لفئة MyCustomization للتعامل بشكل صحيح مع التخلص من الموارد غير المُدارة لفئة MyCustomization، فأنا لا أعرف (حتى الآن) كيفية تشغيل طريقة MyCustomization.Dispose() دون لمس ملف AutogenCls.cs ...(ولكن كما قلت "بعد" :)

لكن هذا الأسلوب يوفر فصلًا رائعًا عن التعليمات البرمجية التي يتم إنشاؤها تلقائيًا - حيث يتم فصل التخصيص بالكامل في ملف كود src مختلف.

يتمتع :)

في الواقع، أصبح هذا ممكنًا الآن، بعد أن تمت إضافة الطرق الجزئية.وهنا الوثيقة:

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

في الأساس، الفكرة هي أنه يمكنك إعلان واستدعاء طريقة في ملف واحد حيث تقوم بتعريف الفئة الجزئية، ولكن لا يمكنك تحديد الطريقة في هذا الملف فعليًا.وفي الملف الآخر، يمكنك بعد ذلك تحديد الطريقة.إذا كنت تقوم بإنشاء تجميع حيث لم يتم تعريف الطريقة، فسيقوم ORM بإزالة كافة الاستدعاءات للوظيفة.

لذلك في الحالة أعلاه سيبدو الأمر كما يلي:

// فئة تم إنشاؤها تلقائيًا

namespace MyNamespace {
   public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol {
      public MyWebService() {
         string myString = "auto-generated constructor";
         OtherCode();
      }
   }
}

partial void OtherCode();

// فئة تم إنشاؤها يدويًا لتجاوز المُنشئ الافتراضي

partial void OtherCode()
{
   //do whatever extra stuff you wanted.
}

إنه محدود إلى حد ما، وفي هذه الحالة بالذات، عندما يكون لديك ملف تم إنشاؤه وتحتاج إلى تعديله، قد لا يكون هذا هو الحل الصحيح، ولكن بالنسبة للآخرين الذين تعثروا في هذا أثناء محاولة تجاوز الوظيفة في الفئات الجزئية، يمكن أن يكون هذا الحل تكون مفيدة للغاية.

والمشكلة التي قد حصلت على OP هي أن وكيل المرجعية على شبكة الإنترنت لا تولد أي أساليب الجزئية التي يمكنك استخدامها لاعتراض المنشئ.

وأنا واجهت نفس المشكلة، وأنا لا يمكن أن الترقية إلى WCF لأن خدمة الإنترنت التي تستهدف أنا لا يعتمد عليه.

وأنا لا أريد أن تعديل قانون يتم إنشاؤه تلقائيا يدويا لأنها سوف تحصل على بالارض إذا كان أي شخص من أي وقت مضى استدعاء الجيل التعليمات البرمجية.

وأنا تناولت المشكلة من زاوية مختلفة. كنت أعرف بلدي التهيئة اللازمة به قبل طلب، فإنه لم يكن في حاجة حقا إلى أن يتم ذلك في وقت البناء، لذلك أنا فقط تجاهلت طريقة GetWebRequest مثل ذلك.

protected override WebRequest GetWebRequest(Uri uri)
{
    //only perform the initialization once
    if (!hasBeenInitialized)
    {
        Initialize();
    }

    return base.GetWebRequest(uri);
}

bool hasBeenInitialized = false;

private void Initialize()
{
    //do your initialization here...

    hasBeenInitialized = true;
}

وهذا هو الحل لطيفة لأنها لا تنطوي على القرصنة التي يتم إنشاؤها تلقائيا الرمز، وتناسبها حالة استخدام الدقيق في OP من أداء تسجيل الدخول التهيئة لSoapHttpClientProtocol السيارات الوكيل الذي تم إنشاؤه.

وأنت لا تستطيع أن تفعل هذا. أنا أقترح استخدام أسلوب الجزئية التي يمكنك بعد ذلك إنشاء تعريف ل. شيء من هذا القبيل:

public partial class MyClass{ 

    public MyClass(){  
        ... normal construction goes here ...
        AfterCreated(); 
    }

    public partial void OnCreated();
}

ويجب أن يكون بقية جميلة النفس التفسيرية.

وتحرير:

وأود أيضا أن أشير إلى أنه يجب عليك أن تحدد واجهة لهذه الخدمة، والتي يمكن بعد ذلك البرنامج، لذلك لم يكن ليكون لدينا ما يشير إلى التنفيذ الفعلي. إذا فعلت هذا فإنك سوف يكون لها بعض الخيارات الأخرى.

وأنا أفكر أنك قد تكون قادرة على القيام بذلك مع PostSharp ، ويبدو كمن لم يفعل فقط ما تريد للطرق في فئات جزئية ولدت . أنا لا أعرف إذا كان هذا سوف تترجم بسهولة إلى القدرة على الكتابة وسيلة ويكون جسمها محل منشئ وأنا لم تعط له رصاصة واحدة حتى الآن ولكن يبدو يستحق رصاصة واحدة.

وتحرير: هذا هو على نفس المنوال وأيضا تبدو مثيرة للاهتمام.

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

والحل أبسط هو على الارجح لإضافة "منشئ" أسلوب واحد الجزئي في الصف الواحد جزئية إضافية:

public partial class MyClass{ 

    public MyClass(){  
        ... normal construction goes here ...
        OnCreated1(); 
        OnCreated2(); 
        ...
    }

    public partial void OnCreated1();
    public partial void OnCreated2();
}

إذا كنت ترغب في فئات جزئية إلى أن يكون الملحد عن بعضها البعض، يمكنك استخدام التفكير:

// In MyClassMyAspect1.cs
public partial class MyClass{ 

    public void MyClass_MyAspect2(){  
        ... normal construction goes here ...

    }

}

// In MyClassMyAspect2.cs
public partial class MyClass{ 

    public void MyClass_MyAspect1(){  
        ... normal construction goes here ...
    }
}

// In MyClassConstructor.cs
public partial class MyClass : IDisposable { 

    public MyClass(){  
       GetType().GetMethods().Where(x => x.Name.StartsWith("MyClass"))
                             .ForEach(x => x.Invoke(null));
    }

    public void Dispose() {
       GetType().GetMethods().Where(x => x.Name.StartsWith("DisposeMyClass"))
                             .ForEach(x => x.Invoke(null));
    }

}

ولكن في الحقيقة أنها ينبغي أن مجرد إضافة بعض اللغات المزيد من يبني للعمل مع فئات جزئية.

لوكيل خدمة ويب التي تم إنشاؤها بواسطة Visual Studio، لا يمكنك إضافة منشئ الخاصة بك في فئة جزئية (وأيضا تستطيع، ولكن لا يحصل يسمى). بدلا من ذلك، يمكنك استخدام السمة [OnDeserialized] (أو [OnDeserializing]) لربط في التعليمات البرمجية الخاصة بك عند نقطة حيث يتم إنشاء مثيل فئة الوكيل على شبكة الإنترنت.

using System.Runtime.Serialization;

partial class MyWebService
{
     [OnDeserialized]
     public void OnDeserialized(StreamingContext context)
     {
         // your code here
     }
}

في بعض الأحيان لم يكن لديك وصول أو غير مسموح لتغيير منشئ افتراضي، لهذا السبب لا يمكن أن يكون منشئ افتراضي لاستدعاء أي الأساليب.

في هذه الحالة يمكنك إنشاء منشئ آخر مع المعلمة وهمية، وجعل هذا البناء الجديد لاستدعاء منشئ افتراضي باستخدام ": هذا ()"

public SomeClass(int x) : this()
{
    //Your extra initialization here
}

وعند إنشاء مثيل جديد من هذه الفئة التي يمر المعلمة همية مثل هذا:

SomeClass objSomeClass = new SomeClass(0);

وليس هناك شيء يمكنني أن أفكر. الطريق "أفضل" أنا يمكن أن تصل هي إضافة المنشئ مع معلمة وهمية واستخدام ما يلي:

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol 
{
   public override MyWebService(int dummy) 
   { 
         string myString = "overridden constructor";
         //other code...
   }
}


MyWebService mws = new MyWebService(0);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top