2011-05-10 13 views
8

के रूप में करते हुए मेरे पास विधियों का एक समूह है जिसे मैं कुछ मेटाडेटा देखना चाहता हूं, उनमें से सभी के पास अलग-अलग पैरामीटर हैं लेकिन सभी पैरामीटर BaseClass से प्राप्त होते हैं।Func <> बेस क्लास का उपयोग पैरामीटर

public void CheckMethod(Func<BaseClass, Object> func) 
{ 
    // Check method metadata here 
} 

public Object MethodToCheck(DerivedClass foo) 
{ 
    // Whatever... 
} 

public void Test() 
{ 
    CheckMethod(MethodToCheck); 
} 

कोड CheckMetadata(MethodToCheck) पर विफल रहता है, क्योंकि MethodToCheck पैरामीटर के रूप में और नहीं एक BaseClass एक DerivedClass है। मैं जेनरिक का उपयोग कर की कोशिश की है:

public void CheckMethod<T>(Func<T, Object> func) 

... 

CheckMethod<DerivedClass>(MethodToCheck); 

मैं CheckMethod करने के लिए कॉल की तरह के रूप में संभव टाइप करने के लिए रूप में छोटे होने के लिए होता है और केवल CheckMethod(MethodToCheck) से कॉल करने के लिए पसंद करेंगे। क्या यह संभव है?

+1

मैं करने के लिए कारण है कि आप एक पूरी तरह से समस्या का समाधान जेनरिक का उपयोग कर के रूप में उत्सुक हूँ, लेकिन आप जा रहा है केवल मापदंड के साथ एक अलग समाधान के लिए देख रहे हैं कि इसे कम टाइपिंग की आवश्यकता होनी चाहिए। आपका लक्ष्य यहाँ क्या है? अपनी प्रोग्रामिंग टीम में आरएसआई को कम करना? –

+0

मुख्य कारण यह है कि मुझे केवल वास्तविक विधि में दिलचस्पी है। लेकिन, तर्क और वापसी डेटा विधि हस्ताक्षर का एक हिस्सा है, इसलिए मुझे लगता है कि यह संभव नहीं है। –

+0

यह वही है जो मैंने अपनी पोस्ट में कहा था :)। मुझे लगता है कि उत्तर के रूप में चिह्नित किया जाना चाहिए। –

उत्तर

2

कैसे

की तरह कुछ के बारे में
public void CheckMethod<T>(Func<T, Object> func) where T : BaseClass 
+0

अभी भी इसे चेकमैड (MethodToCheck) –

-2

एक तरह से BaseClass के स्थान पर dynamic उपयोग करने के लिए होगा:

public void CheckMethod(Func<dynamic, Object> func) 

तो कुछ प्रकार CheckMethod अंदर की जाँच करने के पहले यह देखना होगा कि पैरामीटर प्रकार की है बेसक्लास और शायद फेंक अगर नहीं?

+1

के साथ कॉल करने की आवश्यकता है: परिणाम 1: 'विधि समूह' से 'System.Func में कनवर्ट नहीं किया जा सकता है> ' –

1

Check out the MSDN page on covariance and contravariance। लेख यह सुझाव देता है कि आप इसे पूर्व संस्करणों में प्राप्त नहीं कर सकते हैं।

यदि आप पुराने संस्करण के साथ फंस गए हैं, तो मैं सुझाव दूंगा कि आप विज़िटर पैटर्न का पता लगाएंगे।

+0

मैं जितनी जल्दी हो सके इसे देख लूंगा। –

0

ऐसा लगता है कि सी # भाषा डिजाइनरों ने अभी कुछ नहीं सोचा था। आप (और मैं) फ़ेक्स/प्रतिनिधि के लिए एक संकलन-समय "इंटरफ़ेस" ढूंढ रहे हैं, इसलिए उन्हें अनिवार्य रूप से संग्रह में उपयोग किया जा सकता है।

new[] { 
    new Func<MaxLengthAttribute, string>(a => "maxlength=" + a.Length), 
    new Func<RequiredAttribute, string>(a => "required") 
} 

केवल प्रारूप Func<out Attribute, string> की Funcs पास करने के लिए:

अपने सवाल पूछने का का एक और तरीका है कि कैसे मैं किसी को इस तरह एक सरणी गुजर विवश करते है? सरल होना चाहिए ... नहीं?

नहीं। जैसा कि अन्य उत्तर से जुड़ा हुआ है, इनपुट पैरामीटर पर आउट कीवर्ड की अनुमति नहीं है जैसे कि हम यहां उपयोग कर रहे हैं।

आप संकलन समय आप जावा की तरह बदसूरत कलाबाजी के साथ फंस रहे हैं पर बाधा होना आवश्यक हैं:

public void CheckMethod(IHasMethod methodHaver) 
{ 
} 

Eugh:

public interface IHasMethod<T> 
    where T : BaseClass 
{ 
    void MethodToCheck<T>(T, object); 
} 

public class Class1 : IHasMethod<DerivedClass> 
{ 
    public object MethodToCheck(DerivedClass d) 
    { 

    } 
} 

अपने परीक्षण अर्थ की तरह दिखता है। इसी तरह मेरा सरणी उदाहरण बन जाता है: new IHasMethod[]

यदि आप सुंदर, अधिक चमकदार कोड पसंद करते हैं जो रन-टाइम पर केवल संरक्षित/निरीक्षण किया जाता है तो आपका विकल्प Delegate है।आपके हस्ताक्षर:

public void CheckMethod(Delegate func) 

मेरे सरणी उदाहरण:

new Delegate[] ... 

लेकिन दोनों ही मामलों आप खतरे में हैं, क्योंकि है कि प्रतिनिधि के प्रारूप संकलन समय पर असीम है में - यह आप पर अब क्या करना चाहिए आमतौर पर करते हैं आगे बढ़ने से पहले संकलक की सही संख्या और पैरामीटर की सही संख्या की जांच, संकलक की समस्या हो। यदि आप कर सकते हैं, तो केवल डीबग कोड में बदसूरत जांच करने और यूनिट टेस्ट के लिए निकाली गई विधि के लिए कोई भी कॉल करने की कोशिश करें, भले ही आपने संकलन-सुरक्षा खो दी हो, फिर भी आप इसे स्वचालित परीक्षण सुरक्षा के साथ बदल दें। जैसा:

#if DEBUG 
     foreach(var attrTempl in attributeTemplates) 
     { 
      var templParams = attrTempl.Method.GetParameters(); 
      if (templParams.Length != 1) 
       throw new Exception("Can't have " + templParams.Length + " params in AttributeTemplate Delegate, must be Func<out Attribute, string>"); 

      var type1 = templParams[0].ParameterType; 
      var type2 = attrTempl.Method.ReturnType; 

      if (!type1.IsSubclassOf(typeof(System.Attribute))) 
       throw new Exception("Input parameter type " + type1.Name + " must inherit from System.Attribute"); 

      if (type2 != typeof(string)) 
       throw new Exception("Output parameter type " + type2.Name + " must be string"); 
     } 
#endif 

इस में बाधा दौड़ के लिए एक आखिरी सहायक:

Func<A, B> fn 
इस के लिए

:

Delegate fn 
आप Delegate तरीका अपनाते हैं तो आप कोड है कि इस तरह दिखता है बदल देंगे

शायद आप किसी बिंदु पर फनक पर कॉल करें, जैसे:

var b = fn(a); 

जो अब एक संकलन त्रुटि प्राप्त करेगा, क्योंकि संकलक सटीक रूप से दावा करता है कि यह प्रतिनिधि किसी भी पैरामीटर को स्वीकार नहीं करता है। लवली। आप के साथ अतीत में यह करने के लिए रन-टाइम बाज़ी कर सकते हैं:

var b = (B)fn.DynamicInvoke(a); 

Related

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