سؤال

لنفترض أن لدي خدمة ويب ASMX، MyService.الخدمة لديها طريقة MyMethod.يمكنني تنفيذ MyMethod على جانب الخادم كما يلي:

MyService service = new MyService();
service.MyMethod();

أحتاج إلى القيام بالمثل، مع الخدمة والطريقة غير المعروفة حتى وقت التشغيل.

أفترض أن التفكير هو الطريقة للقيام بذلك.لسوء الحظ، أواجه صعوبة في جعله يعمل.عندما أقوم بتنفيذ هذا الكود:

Type.GetType("MyService", true);

يلقي هذا الخطأ:

تعذر تحميل النوع "MyService" من التجميع "App_Web__ktsp_r0، الإصدار=0.0.0.0، Culture=محايد، PublicKeyToken=null".

سيكون موضع تقدير أي توجيه.

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

المحلول

لست متأكدًا مما إذا كانت هذه هي أفضل طريقة للقيام بذلك.الطريقة الأكثر وضوحًا بالنسبة لي هي تقديم طلب HTTP، والاتصال بخدمة الويب باستخدام HTTP GET أو POST الفعلي.باستخدام طريقتك، لست متأكدًا تمامًا من كيفية إعداد البيانات التي ترسلها إلى خدمة الويب.لقد أضفت بعض نماذج التعليمات البرمجية في VB.Net

Dim HTTPRequest As HttpWebRequest
Dim HTTPResponse As HttpWebResponse
Dim ResponseReader As StreamReader
Dim URL AS String
Dim ResponseText As String

URL = "http://www.example.com/MyWebSerivce/MyMethod?arg1=A&arg2=B"

HTTPRequest = HttpWebRequest.Create(URL)
HTTPRequest.Method = "GET"

HTTPResponse = HTTPRequest.GetResponse()

ResponseReader = New StreamReader(HTTPResponse.GetResponseStream())
ResponseText = ResponseReader.ReadToEnd()

نصائح أخرى

// جرب هذا ->

    Type t = System.Web.Compilation.BuildManager.GetType("MyServiceClass", true);
    object act = Activator.CreateInstance(t);                
    object o = t.GetMethod("hello").Invoke(act, null);

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

اجعل خدمة الويب الخاصة بك بسيطة، وضحلة، باختصار:تنفيذ نمط الواجهة.

قم بإجراء حساب مندوب الخدمة الخاص بك إلى فئة التنفيذ، والتي يجب أن تكون قابلة للاستدعاء بسهولة من خلال الانعكاس.بهذه الطريقة، تكون فئة WebService الخاصة بك مجرد واجهة لنظامك - يمكنك أيضًا إضافة معالج بريد إلكتروني، وواجهة XML-RPC الأمامية وما إلى ذلك، نظرًا لأن منطقك لا يقترن بخدمة WebService، بل بكائن طبقة أعمال فعلي.

فكر في فئات WebService ككائنات طبقة واجهة المستخدم في الهندسة المعمارية الخاصة بك.

إليك إجابة سريعة ربما يمكن لأي شخص التوسع فيها.

عند استخدام تطبيق قوالب WSDL (WSDL.exe) لإنشاء أغلفة الخدمة، فإنه ينشئ فئة من النوع SoapHttpClientProtocol.يمكنك القيام بذلك يدويًا أيضًا:

public class MyService : SoapHttpClientProtocol
{
    public MyService(string url)
    {
        this.Url = url;
        // plus set credentials, etc.
    }

    [SoapDocumentMethod("{service url}", RequestNamespace="{namespace}", ResponseNamespace="{namespace}", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    public int MyMethod(string arg1)
    {
        object[] results = this.Invoke("MyMethod", new object[] { arg1 });
        return ((int)(results[0]));
    }
}

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

الرمز الذي قدمته هو رمز المتصل الذي يتصل بخدمة الويب عبر مكالمة عن بعد (حتى لو كنت لا تريد أن يكون بعيدًا لأي سبب من الأسباب.) تعتني طريقة الاستدعاء بتعبئته كرمز نداء الصابون.رمز @ Dave Ward صحيح إذا كنت تريد تجاوز استدعاء خدمة الويب عبر HTTP - طالما أنك قادر بالفعل على الرجوع إلى الفصل الدراسي.ربما يكون النوع الداخلي ليس "MyService" - سيتعين عليك فحص رمز التحكم للتأكد من ذلك.

@ كيبي:أحتاج إلى تجنب أداء HTTP.لن تكون مكالمة عن بعد، لذا كل ذلك أضاف عبئًا إضافيًا يجب تكون غير ضرورية.

@ دارين:وأنا أتفق بالتأكيد مع فلسفة التصميم تلك.المشكلة هنا هي أنني لن أتحكم في الخدمة أو منطق العمل الأساسي الخاص بها.

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

على الرغم من أنني لا أستطيع أن أقول من رسالتك:

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

لذلك إذا كان لديك خدمة ويب

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    public class WebService1 : System.Web.Services.WebService
    {
     ...
    }

لا يمكنك الرجوع إلى هذا التجميع في عميلك والقيام بشيء مثل:

WebService1  ws = new WebService1 ();
ws.SomeMethod();

@رادو:أنا قادر على إنشاء مثيل واستدعاء الطريقة تمامًا مثل ذلك.على سبيل المثال، إذا كان لدي ASMX:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class MyService : System.Web.Services.WebService
{
  [WebMethod]
  public string HelloWorld()
  {
    return "Hello World";
  }
}

يمكنني الاتصال به من الكود الخلفي لصفحة ASPX مثل هذا:

MyService service = new MyService();
Response.Write(service.HelloWorld());

هل تقول أن هذا لا ينبغي أن يعمل؟

لقد نظرت مرة أخرى إلى هذا السؤال وأعتقد أن ما تواجهه هو أن كود ASMX سيتم دمجه في ملف DLL باسم عشوائي كجزء من التجميع الديناميكي لموقعك.بشكل افتراضي، سوف تبحث التعليمات البرمجية الخاصة بك للبحث عن النوع فقط في التجميع الخاص به (ملف App_Code DLL آخر، حسب مظهر الخطأ الذي تلقيته) والمكتبات الأساسية.يمكنك توفير مرجع تجميع محدد "TypeName, AssemblyName" إلى GetType() ولكن هذا غير ممكن في حالة التجميعات التي تم إنشاؤها تلقائيًا، والتي لها أسماء جديدة بعد كل إعادة ترجمة.

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

System.Web.Compilation.BuildManager.GetType("MyService", true)

نظرًا لأن BuildManager على علم بمكتبات الارتباط الحيوي (DLL) التي قام بإنشائها ويعرف أين يبحث عنها.

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

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