2012-01-16 9 views
7

मैं कोड निम्नलिखित है:जेनेरिक इंटरफेस और बहुरूपता

public abstract class Operand<T> 
{ 
    public T Value { get; protected set; } 

    public bool IsEmpty { get; protected set; } 

    public override string ToString() 
    { 
     return IsEmpty ? Value.ToString() : string.Empty; 
    } 
} 
public class DoubleOperand : Operand<Double> {} 

public interface IOperandFactory<T> 
    { 
     Operand<T> CreateEmptyOperand(); 
     Operand<T> CreateOperand(T value); 
    } 

public class DoubleFactory: IOperandFactory<double> 
{ 
    public Operand<Double> CreateEmptyOperand() 
    { 
     //implementation 
    } 

    public Operand<Double> CreateOperand(double value) 
    { 
     //implementation 
    } 
} 

मैं कोड simlified सिर्फ संरचना दिखाने के लिए। अब मैं associationDictionary जरूरत है कि आवश्यक Type के लिए IOperandFactory वापस आ जाएगी: कुछ इस तरह:

var factoryDict = 
new Dictionary<Type, IOperandFactory<>>() { { typeof(double), new DoubleFactory() } }; 

आप अगर यह संभव है मुझे इसे प्राप्त करने में मदद कर सकता है?

उत्तर

7

कि ऐसा करने के लिए, आप एक गैर सामान्य इंटरफ़ेस है की आवश्यकता होगी (आमतौर पर सामान्य इंटरफ़ेस के अलावा), यानी एक गैर सामान्य Operand, Operand<T> : Operand (यह भी एक इंटरफेस हो सकता है) के साथ, और एक गैर सामान्य IOperandFactoryIOperandFactory<T> : IOperandFactory के साथ। एकमात्र अन्य विकल्प Dictionary<Type, object> स्टोर करना है, और कॉलर को आवश्यकतानुसार डालना है।

using System.Collections.Generic; 
using System; 
public interface IOperand 
{ 
    object Value { get; } 
    bool IsEmpty { get; } 
} 
public abstract class Operand<T> : IOperand 
{ 
    public T Value { get; protected set; } 
    object IOperand.Value { get { return Value; } } 
    public bool IsEmpty { get; protected set; } 
    public override string ToString() 
    { 
     return IsEmpty ? Value.ToString() : string.Empty; 
    } 
} 
public class DoubleOperand : Operand<double> { } 

public interface IOperandFactory 
{ 
    IOperand CreateEmptyOperand(); 
    IOperand CreateOperand(object value); 
} 
public interface IOperandFactory<T> : IOperandFactory 
{ 
    new Operand<T> CreateEmptyOperand(); 
    Operand<T> CreateOperand(T value); 
} 

public class DoubleFactory : IOperandFactory<double> 
{ 
    public Operand<double> CreateEmptyOperand() 
    { 
     throw new NotImplementedException(); 
    } 
    IOperand IOperandFactory.CreateEmptyOperand() { 
     return CreateEmptyOperand(); 
    } 

    IOperand IOperandFactory.CreateOperand(object value) { 
     return CreateOperand((double)value); 
    } 
    public Operand<double> CreateOperand(double value) 
    { 
     throw new NotImplementedException(); 
    } 
} 

static class Program 
{ 
    static void Main() 
    { 
     var factoryDict = new Dictionary<Type, IOperandFactory> { 
      {typeof (double), new DoubleFactory()} 
     }; 
    } 
} 
+0

त्वरित जवाब के लिए धन्यवाद। – Danil

+0

@Danil I ने एक पूर्ण उदाहरण में संपादित किया, अगर यह –

+0

हाँ मदद करता है, धन्यवाद, मुझे लगता है कि यह अन्य उपयोगकर्ताओं के लिए भी उपयोगी होगा। – Danil

2

अगर मैं सही ढंग से समझ, आप सामान्य प्रकार है, जहां सामान्य प्रकार पैरामीटर भिन्न हो सकते हैं का एक संग्रह स्टोर करने के लिए कोशिश कर रहे हैं:

यहाँ गैर सामान्य तरीका है। यदि यह मामला है, यह सीधे संभव नहीं है, जैसा कि निम्न उदाहरण दिखाता है:

// You have lists of different types: 
List<double> doubleCollection = new List<double>(); 
List<string> stringCollection = new List<string>(); 

// Now to store generically: 
var collection = new List<List< /* ... Which type parameter to use? ... */ >>(); 

क्या यहाँ स्पष्ट होना चाहिए, कि यह संभव किस प्रकार पैरामीटर का उपयोग करने निकालना नहीं है। इसके बजाय (अपने उदाहरण के संबंध में), तो आप इस बजाय की तरह कुछ कर सकते हैं:

public interface IOperand 
{ 
} 

public interface IOperand<T> 
{ 
} 

public interface IOperandFactory 
{ 
    IOperand CreateEmptyOperand(); 
    IOperand CreateOperand(object value); 
} 

public interface IOperandFactory<T> : IOperandFactory 
{ 
    new IOperand<T> CreateEmptyOperand(); 
    IOperand<T> CreateOperand(T value); 
} 

public class DoubleFactory : IOperandFactory<double> 
{ 
    public IOperand<double> CreateEmptyOperand() 
    { 
     throw new NotImplementedException(); 
    } 

    public IOperand<double> CreateOperand(double value) 
    { 
     throw new NotImplementedException(); 
    } 

    IOperand IOperandFactory.CreateEmptyOperand() 
    { 
     throw new NotImplementedException(); 
    } 

    public IOperand CreateOperand(object value) 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class SomeContainer 
{ 
    public SomeContainer() 
    { 
     var factoryDict = new Dictionary<Type, IOperandFactory>() 
     { 
      { typeof(double), (IOperandFactory)new DoubleFactory() } 
     }; 
    } 
} 

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

// ... Inside SomeContainer ... 
public IOperandFactory<T> GetFactory<T>() 
{ 
    return (IOperandFactory<T>)factoryDict[typeof(T)]; 
} 

तो इस के साथ, आप DoubleFactory का उपयोग कर प्राप्त कर सकते हैं:

IOperandFactory<double> doubleFactory = mSomeContainerInstance.GetFactory<double>(); 
IOperand<double> emptyOperand = doubleFactory.CreateEmptyOperand(); 
IOperand<double> filledOperand = doubleFactory.CreateOperand(1.0d);