2009-09-14 20 views
10

हमारे पास एक ऐप है जो वैकल्पिक रूप से टीएफएस के साथ एकीकृत करता है, हालांकि एकीकरण वैकल्पिक है, इसलिए स्पष्ट रूप से सभी मशीनों को टीएफएस असेंबली को की आवश्यकता नहीं है।वैकल्पिक निर्भरताओं से निपटना (सी #)

मुझे क्या करना चाहिए?

  1. यह ठीक मुझे मेरे मुख्य विधानसभाओं में TFS लाइब्रेरियों को संदर्भित करने और बस सुनिश्चित करें कि मैं केवल TFS संबंधित वस्तुओं को संदर्भित जब मैं TFS एकीकरण उपयोग कर रहा हूँ बनाने के लिए है।
  2. वैकल्पिक रूप से सुरक्षित विकल्प कुछ अलग "TFSWrapper" विधानसभा में TFS लाइब्रेरियों को संदर्भित करने होगा:

    एक। क्या यह मेरे लिए उस असेंबली को सीधे संदर्भित करने के लिए ठीक है (जब तक मैं जो कहता हूं उसके बारे में सावधान रहूं)

    बी। क्या मुझे इसके बजाय मेरे TFSWrapper असेंबली को कार्यान्वित करने के लिए इंटरफेस का एक सेट उजागर करना चाहिए, और फिर आवश्यकता होने पर प्रतिबिंब का उपयोग करके उन वस्तुओं को तुरंत चालू करना चाहिए।

1 मुझे जोखिम भरा लगता है, फ्लिप पक्ष 2 बी पर शीर्ष पर लगता है - मैं अनिवार्य रूप से प्लग-इन सिस्टम का निर्माण कर रहा हूं।

निश्चित रूप से एक आसान तरीका होना चाहिए।

+0

इस मामले में "टीएफएस" "टीम फाउंडेशन सिस्टम" है, है ना? –

+0

हां, लेकिन मैं इस सवाल को टीएफएस के बारे में कम मानता हूं और असेंबली को संदर्भित करने का सबसे अच्छा तरीका है जो कुछ उपयोगकर्ता मशीनों पर मौजूद नहीं हो सकता है। – Justin

+0

डी ओह, मैंने पहले वाक्य को ध्यान से पर्याप्त रूप से नहीं पढ़ा, इसलिए मुझे एहसास नहीं हुआ कि 'वैकल्पिक' से आपका मतलब है 'उपयोगकर्ता की मशीन पर मौजूद नहीं हो सकता है।' –

उत्तर

6

सबसे सुरक्षित तरीका है (यानी सबसे आसान तरीका है अपने आवेदन में एक गलती नहीं बनाने के लिए) के रूप में हो सकता है।

एक अंतरफलक जो उदाहरण के लिए, TFS के आपके उपयोग abstracts करें:

class Tfs : ITfs 
{ 
    public bool checkout(string filename) 
    { 
    ... code here which uses the TFS assembly ... 
    } 
} 

अन्य वर्ग जो का उपयोग किए बिना इस इंटरफेस को लागू करता है लिखें:

interface ITfs 
{ 
    bool checkout(string filename); 
} 

एक वर्ग जो इस इंटरफेस TFS का उपयोग कर लागू करता लिखें टीएफएस:

class NoTfs : ITfs 
{ 
    public bool checkout(string filename) 
    { 
    //TFS not installed so checking out is impossible 
    return false; 
    } 
} 

कहीं सिंगलटन है:

static class TfsFactory 
{ 
    public static ITfs instance; 

    static TfsFactory() 
    { 
    ... code here to set the instance 
    either to an instance of the Tfs class 
    or to an instance of the NoTfs class ... 
    } 
} 

अब सिर्फ एक ही जगह है, जो सावधान रहने की जरूरत है है (अर्थात TfsFactory निर्माता); आपका शेष कोड यह जानने के बिना कि TFS स्थापित है या नहीं, आपके TfsFactory.instance के ITfs विधियों का आह्वान कर सकता है।


नीचे हाल की टिप्पणियों का जवाब करने के लिए:

मेरी परीक्षण के अनुसार (मैं नहीं जानता कि यह है 'परिभाषित व्यवहार' है या नहीं) एक अपवाद फेंक दिया जाता है जब (जैसे ही) यदि आप एक विधि कॉल जो लापता असेंबली पर निर्भर करता है। इसलिए आपके असेंबली में कम-से-कम एक अलग विधि (या एक अलग वर्ग) में आपके कोड-जो-निर्भर-पर-अनुपलब्ध-असेंबली को समाहित करना महत्वपूर्ण है।

उदाहरण के लिए, निम्नलिखित यदि टॉक विधानसभा याद आ रही है लोड नहीं होगा:

using System; 
using OptionalLibrary; 

namespace TestReferences 
{ 
    class MainClass 
    { 
     public static void Main(string[] args) 
     { 
      if (args.Length > 0 && args[0] == "1") { 
       Talk talk = new Talk(); 
       Console.WriteLine(talk.sayHello() + " " + talk.sayWorld() + "!"); 
      } else { 
       Console.WriteLine("2 Hello World!"); 
      } 
     } 
    } 
} 

निम्नलिखित इच्छा लोड:

using System; 
using OptionalLibrary; 

namespace TestReferences 
{ 
    class MainClass 
    { 
     public static void Main(string[] args) 
     { 
      if (args.Length > 0 && args[0] == "1") { 
       foo(); 
      } else { 
       Console.WriteLine("2 Hello World!"); 
      } 
     } 

     static void foo() 
     { 
      Talk talk = new Talk(); 
      Console.WriteLine(talk.sayHello() + " " + talk.sayWorld() + "!"); 
     } 
    } 
} 

ये परीक्षण के परिणाम (MSVC# 2010 का उपयोग कर रहे हैं और विंडोज़ पर .NET):

C:\github\TestReferences\TestReferences\TestReferences\bin\Debug>TestReferences.exe 
2 Hello World! 

C:\github\TestReferences\TestReferences\TestReferences\bin\Debug>TestReferences.exe 1 

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'OptionalLibrary, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. 
    at TestReferences.MainClass.foo() 
    at TestReferences.MainClass.Main(String[] args) in C:\github\TestReferences\TestReferences\TestReferences\Program.cs: 
line 11 

C:\github\TestReferences\TestReferences\TestReferences\bin\Debug> 
+0

लेकिन आपकी कहानियां यह ठीक है कि टीएफएस वर्ग के कार्यान्वयन एक ही असेंबली के अंदर रहता है? – Justin

+0

पारंपरिक विंडोज एपीआई का उपयोग करना, यदि आप एक डीएलएल से लिंक करते हैं जो एंड-यूजर मशीन पर मौजूद नहीं है तो आपका निष्पादन योग्य बिल्कुल लोड नहीं होगा: और इसलिए, आपको स्पष्ट लोड लाइब्रेरी का उपयोग करने की आवश्यकता है। मुझे यकीन नहीं है कि मैंने इसका परीक्षण किया है, लेकिन मुझे विश्वास नहीं है कि यह उन विधानसभाओं के डॉटनेट संदर्भों के सत्य है जो एंड-यूजर मशीन पर मौजूद नहीं हैं ... और इसलिए आपके संदर्भ में यह संदर्भ सुरक्षित है असेंबली (केवल एक रन-टाइम अपवाद होगा जब आप गैर-मौजूदा असेंबली को कॉल करने का प्रयास करेंगे)। – ChrisW

+0

इससे TfsFactory TFS क्लास युक्त असेंबली पर निर्भर करेगा। और चूंकि एप्लिकेशन में TfsFactory का उपयोग किया जाता है, फिर भी इसे "वैकल्पिक" Tfs dll के साथ सॉफ़्टवेयर वितरित करने की आवश्यकता होगी। :-) –

0

एक "प्लग-इन" अवधारणा जाने का रास्ता हो सकता है, और यह भी (बाद में) TFS के अलावा अन्य उत्पादों के साथ काम करने के लिए यदि आवश्यक हो तो अपने आवेदन का विस्तार करने के लिए आप की अनुमति दे सकता। विकल्प 2 ए बस के रूप में "जोखिम भरा" दोनों अपने अनुप्रयोग और से (नाकाम रहने जब लिंक की गई फ़ाइलों याद कर रहे हैं) विकल्प 1.

आप अपने विशिष्ट प्रयोजन के लिए आवश्यक इंटरफेस के साथ एक विधानसभा बना सकते हैं के रूप में, और संदर्भ इस विधानसभा हो जाएगा "टीएफएस प्लग-इन"। उत्तरार्द्ध तब आपके इंटरफेस के कार्यान्वयन प्रदान करता है और संचालन करने के लिए टीएफएस का उपयोग करता है। ऐप गतिशील रूप से एक असेंबली लोड कर सकता है और आवश्यक प्लग-इन प्रकारों के उदाहरण बना सकता है (Activator आदि के माध्यम से) और उन उदाहरणों को अपने इंटरफेस पर डालें।

वास्तव में, यदि आप उन प्रकारों को MarshalByRef से प्राप्त करते हैं, तो आप उन्हें AppDomain में भी लोड कर सकते हैं और इस प्रकार अपने प्लगइन का एक साफ अलगाव कर सकते हैं, और उन्हें अनलोड करने योग्य भी बना सकते हैं।

+0

मैं वास्तव में एक प्लग-इन सिस्टम को लागू करने की कोशिश कर रहा हूं। हालांकि, कभी-कभी मैं किसी अन्य असेंबली में पेश किए गए एक प्रकार का उपयोग करना चाहता हूं। इस प्रकार का उपयोग करने वाले कोड को "if" कथन से संरक्षित किया जाएगा जो गारंटी देगा कि यह केवल तब उपयोग किया जाता है जब लाइब्रेरी उपलब्ध हो और लोड हो। क्या सी # में ऐसा करने का कोई तरीका है? –

+0

@SergiyByelozyorov, हाँ यह किया जा सकता है, लेकिन केवल देर से बाध्यकारी (उदा। प्रतिबिंब या गतिशील) के माध्यम से। यदि प्रकार कुछ इंटरफ़ेस को कार्यान्वित कर सकता है जो हमेशा उपलब्ध होता है तो यह उपयोग करने के लिए और अधिक सुविधाजनक बना देगा। – Lucero

1

आप Managed Extensibility Framework (MEF) देख सकते हैं।

+0

यह बहुत दिलचस्प लग रहा है, हालांकि इस समय मैं जो कुछ भी कर रहा हूं उसके लिए संभवतः शीर्ष पर थोड़ा सा! हालांकि मैं शायद बाद में एक नज़र डालेगा। – Justin

संबंधित मुद्दे