2010-02-17 12 views
5

में जाना जाता है मैं की तरह एक सामान्य इंटरफ़ेस का उपयोग करने की आवश्यकता है लौटने के बाद:समारोह एक सामान्य प्रकार जिसका मूल्य केवल क्रम

public interface IContainer<T> 
{ 
    IEnumerable<IContent<T>> Contents { get; } 
} 

इस इंटरफेस को लागू करने वाली वस्तु निम्नलिखित की तरह एक सामान्य विधि द्वारा दिया जाता है:

IContainer<T> GetContainer<T>(IProperty property); 

टाइप T रन-टाइम तक अज्ञात है।

प्रतिबिंब का उपयोग करके मैं GetContainer<T> विधि का आह्वान करने और परिणाम प्राप्त करने में सक्षम हूं।

मेरी समस्या यह है कि मुझे नहीं पता कि परिणाम Object के परिणाम को कैसे समझा जाए (इसलिए मैं इसे IEnumerable पर नहीं डाल सकता)।

मैं भी इस प्रकार है, लेकिन यह काम नहीं करता है के रूप में कास्टिंग (यह कहते हैं, "प्रकार की उम्मीद है") की कोशिश की है: सेवा GetContainer<T> विधि उजागर कर रहा है

var myContainer = genericMethodInfo.Invoke(
          myService, 
          new object[] { property }) 
    as typeof(IContainer<>).MakeGenericType(type); 

जहां type क्रम प्रकार है, myService, और property आवश्यकतानुसार IProperty प्रकार है।

अद्यतन: अपने ब्लॉग में मेरा पूरा समाधान देखें: http://stefanoricciardi.com/2010/02/18/generics-with-type-uknown-at-compile-time/

+0

संभव डुप्लिकेट (http://stackoverflow.com/questions/232535/how- उपयोग करने के लिए प्रतिबिंब-टू-कॉल-जेनेरिक-विधि) – nawfal

उत्तर

1

टाइपऑफ (आईकॉन्टेनर <>)। मेकजेनरिक टाइप (प्रकार) केवल रनटाइम पर मूल्यांकन करेगा, जबकि "as" को कंपाइलर समय पर प्रकार जानने की आवश्यकता है।

जो मैं वास्तव में समझ में नहीं आता वह यह टिप्पणी है: मेरी समस्या यह है कि मुझे नहीं पता कि परिणाम का आकलन कैसे करें जिसमें ऑब्जेक्ट टाइप किया गया है (इसलिए मैं इसे IENumerable में नहीं डाल सकता)।

myContainer एक ऑब्जेक्ट हो सकता है लेकिन यह निश्चित रूप से IENumerable पर डाला जा सकता है? यदि ऐसा नहीं किया जा सकता है तो इसे समझा नहीं जा सकता है।

1

आपका प्रकार टी संकलक द्वारा पता होना चाहिए, तो यह काम नहीं करेगा। आप अपने इंटरफेस के एक गैर जेनेरिक वर्जन बनाने इस तरह की कोशिश कर सकते हैं:

public interface IContainer 
{ 
    IEnumerable<IContent> Contents { get; } 
} 

public interface IContainer<T> : IContainer { ... } 

इस तरह से आप को कास्ट करने के लिए कुछ है और इसका इस्तेमाल करने में सक्षम हैं।

0

यदि आप .Net 4 पर जाने की सोच रहे हैं तो dynamic प्रकार प्रदान करता है।

0

मुझे लगता है कि आपकी वस्तु केवल प्रतिबंधित संख्याओं में से एक होने के रूप में वापस आ जाएगी, तो क्यों कास्टिंग करने से पहले उन लोगों के खिलाफ परीक्षण न करें। अगर वस्तु इस वर्ग है?

+0

दुर्भाग्य से मैं ऐसी धारणा नहीं बना सकता क्योंकि मेरा कोड लाइब्रेरी का हिस्सा है जिसका पुन: उपयोग किया जा सकता है। जबकि मुझे पता है कि ज्यादातर तार, युगल और दशमलव को संभाला जाएगा, मैं अन्य प्रकारों को "प्राथमिकता" को बाहर नहीं कर सकता। यदि अन्य सभी विफल हो जाते हैं, हालांकि, मुझे उस मार्ग पर जाना होगा और अप्रत्याशित प्रकारों के लिए अपवाद उठाना होगा। –

+0

@Stefano - अपने ऑब्जेक्ट प्रकार का परीक्षण IENumerable के विरुद्ध करें जिससे आप यह सुनिश्चित कर सकें कि आपने इसे केवल डाला है। फोरैच स्टेटमेंट में उपयोग के लिए, यदि आपकी ऑब्जेक्ट क्लास आईनेमरेबल को प्राप्त करती है। – ChrisBD

0

क्षमा करें अगर मुझे गलत समझा जाता है, तो मुझे यह समझने में परेशानी हो रही थी कि आपका उद्देश्य क्या था। क्या आप इस तरह कुछ ढूंढ रहे थे?

var myContainer = typeof(ClassWithGetContainer) 
       .GetMethod("GetContainer") 
       .MakeGenericMethod(runtimeType) 
       .Invoke(InstanceOfClassWithGetContainer, new object[] { property }); 
+0

नहीं, मैं पहले से ही इस बिंदु से पहले हूं। मैंने पहले से ही myContainer populated है और यह काम कर रहा है। मेरी समस्या बाद में आती है, जो कंटेनर से एकल सामग्री को पुनर्प्राप्त कर रही है। –

1

सबसे पहले, जब आपको कास्टिंग करने के लिए आपको एक प्रकार (डबल, int) की आवश्यकता होती है; टाइपफ एक प्रकार का तर्क लेता है और टाइप प्रकार का प्रकार देता है।

 object x = 0.0; 
    Type t = typeof(double); 
    double y = x as t; //does not compile - t is not a type - it's an instance of type Type 
    double y = x as typeof(double); //same as above 
    double y = x as double; //compiles - double is a type 
    Type z = x as Type; //compiles - Type is a type 

दूसरा, यहाँ कुछ उदाहरण कोड है: [? कैसे प्रतिबिंब का उपयोग करने के सामान्य विधि कॉल करने के लिए]

using System; 
using System.Collections.Generic; 
using System.Collections; 
using System.Reflection; 
using System.Diagnostics; 

namespace TryThis 
{ 
    public interface IContainer<T> 
    { 
     IEnumerable<IContent<T>> Contents { get; } 
    } 
    public interface IContent<T> 
    { 
     T GetMyContent(); 
    } 
    public interface IProperty 
    { } 

    public class Content<T> : IContent<T> 
    { 
     T m_content = default(T); 
     public T GetMyContent() { return m_content; } 
     public Content(T val) { m_content = val; } 
    } 

    public class Contents<T> : IEnumerable<IContent<T>> 
    { 
     List<IContent<T>> m_contents = new List<IContent<T>>(); 
     IEnumerator<IContent<T>> IEnumerable<IContent<T>>.GetEnumerator() { return m_contents.GetEnumerator(); } 
     IEnumerator IEnumerable.GetEnumerator() { return m_contents.GetEnumerator(); } 
     public Contents(params T[] contents) { foreach (T item in contents) m_contents.Add(new Content<T>(item)); } 
    } 

    public class TestGenericContent : IContainer<int> 
    { 
     public IContainer<int> GetContainer(IProperty property) { return this; } 
     public IEnumerable<IContent<int>> Contents { get { return new Contents<int>(1, 2, 3); } } 
    } 

    public static class TryThisOut 
    { 
     static void Test2(object o) 
     { 
     Type t = o.GetType(); 
     Type tInterface = t.GetInterface("IContainer`1"); //could be null if o does not implement IContainer<T> 
     Type tGenericArg = tInterface.GetGenericArguments()[0]; //extracts T from IContainer<T> 
     MethodInfo info = t.GetMethod("GetContainer"); 
     IProperty propArg = null; //null in this example 
     object oContainer = info.Invoke(o, new object[] { propArg }); 

     PropertyInfo prop = tInterface.GetProperty("Contents"); 
     object oContents = prop.GetGetMethod().Invoke(oContainer, null); 
     //oContents is of type IEnumerable<IContent<T>>, which derives from IEnumerable, so we can cast 
     IEnumerable enumeratedContents = oContents as IEnumerable; 

     MethodInfo getContentItem = typeof(IContent<>).MakeGenericType(tGenericArg).GetMethod("GetMyContent"); 
     foreach (object item in enumeratedContents) 
     {    
      object oContentItem = getContentItem.Invoke(item, null); 
      Debug.Print("Item {0} of type {1}", oContentItem, oContentItem.GetType()); 
      //... 
     } 
     } 

     public static void Test() 
     { 
     object o = new TestGenericContent(); 
     Test2(o); 
     } 
    } 
} 
की
संबंधित मुद्दे