2012-01-16 10 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。 は今、私は必要なTypeためIOperandFactoryを返すようassociationDictionaryが必要になります。 このような何か:それは可能であれば

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

あなたがそれを達成するために私を助けてもらえますか?

答えて

7

これを行うには、非汎用インターフェイス(通常は汎用インターフェイスに加えて)、つまり非汎用のOperandOperand<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

@ダニル私はそれが役に立ったならば、完全な例で編集した –

+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); 
関連する問題