2012-04-13 17 views
5

私は数時間問題を解決してきましたが、近いと思います。私は同じ方法を実行する50〜100種類を持つことができるアプリケーションに取り組んでいます。だからではなく、50-100クラスを作成するので、私はそれが一般的な作ってみました、これは私が持っているものである:これは、基本クラスである実行時に汎用インターフェイスを使用して汎用タイプを作成

public class RavenWriterBase<T> : IRavenWriter<T> where T : class, IDataEntity 

そして、これはインターフェイスです:

public interface IRavenWriter<T> 
{ 
    int ExecutionIntervalInSeconds { get; } 
    void Execute(object stateInfo); 
    void Initialize(int executionIntervalInSeconds, Expression<Func<T, DateTime>> timeOrderByFunc); 
} 

そして、これは私がそれを使用している方法です:

private static void StartWriters() 
{ 
    Assembly assembly = typeof(IDataEntity).Assembly; 
    List<IDataEntity> dataEntities = ReflectionUtility.GetObjectsForAnInterface<IDataEntity>(assembly); 

    foreach (IDataEntity dataEntity in dataEntities) 
    { 
     Type dataEntityType = dataEntity.GetType(); 
     Type ravenWriterType = typeof(RavenWriterBase<>).MakeGenericType(dataEntityType); 

     Expression<Func<IDataEntity, DateTime>> func = x => x.CicReadTime; 

     // This is where I'm stuck. How do I activate this as RavenWriterBase<T>? 
     var ravenWriter = Activator.CreateInstance(ravenWriterType); 

     //ravenWriter.Initialize(60, func); // I can't do this until I cast. 

     // More functionality here (not part of this issue) 
    } 
} 

私は上からこの行にこだわっている:

var ravenWriter = Activator.CreateInstance(ravenWriterType); 

これが私の質問です:
にはどうすればRavenWriterBaseまたはIRavenWriterとすることを使用することができますか?ような何か:

ravenWriter.Initialize(60, func); 

私はそれがこのようなものにする必要があると思いますが、私はIRavenWriter <のための型を指定する必要があります>と、私はまだそれを知らない:

var ravenWriter = Activator.CreateInstance(ravenWriterType) as IRavenWriter<>; 

もし私がravenWriter上にカーソルを移動、私は正常に私のオブジェクトがあります。

enter image description here

をしかし、今、私は一般的な方法でそれを使用できるようにする必要があります。どうやってやるの?

更新:

私はちょうどdynamicキーワードを使用して考えると、これは動作します:

dynamic ravenWriter = Activator.CreateInstance(ravenWriterType); 
ravenWriter.Initialize(60); 

私はfuncは各IDataEntityのために同じであったことに気づいたので、私はそう、少しだまさInitialize()にパラメータとして渡す必要はありませんでした。しかし、少なくとも今では私はを呼び出すInitialize()。しかし、Funcが同じになったので、汎用インターフェースも必要ないはずです。

+2

ジェネリックの不適切な使用のように聞こえます。さまざまな型に基づいて異なるメソッドを実行する必要があるが、実行時にしか型がわからない場合は、多態性を使用する必要があります。ジェネリックスはあなたを獲得していますか?最初にジェネリックスなしで、つまりIDataEntityを使用してメソッドをそのまま実行できますか? – mellamokb

+1

私はmellamokbに同意します。しかし、ジェネリックスに設定されている場合、非genarをインスタンス化できるラッパークラスを作成しないでください。ラッパーには、引数として渡される型に応じて、RavenWriterBase のインスタンスを返すメソッドが必要です。次に、ラッパーをインスタンス化し、要求されたdタイプをパラメーターとしてメソッドを呼び出します。これには、大きなswitch文が必要ですが、少なくとも200個の異なるクラスが必要です。 – dcow

+2

IDataEntity for Tを使用しない他の式を作成しますか?またはTは常にIDataEntityですか?そして、Tが常にIDataEntityなら、なぜジェネリックを使うのですか? –

答えて

2

私のソリューションは、に次のようになります。IRavenWriter

  • の非ジェネリックインターフェイスを作成

    • IRavenWriter
    • からIRavenWriter<T>継承を作るIRavenWriterFunc<DateTime>と使用を持っていることを確認しIRavenWriter
    • ExecuteExecutionIntervalInSecondsをキープそれはあなたの作家で
    • Mたとえば、

    :オベInitializeIRavenWriter<T>

  • に種類や表現に応じてのFuncを初期化するために工場を使用し

    public class MyDateTime 
    { 
        public DateTime This { get; set; } 
    } 
    
    public static Func<DateTime> GetFunk<T>(Expression<Func<T, DateTime>> timeOrderByFunc, T t) 
    { 
        return() => timeOrderByFunc.Compile()(t); 
    } 
    

    そして、あなたが使用します。

    GetFunk<MyDateTime>(x => x.This, new MyDateTime(){This = DateTime.Now}); 
    
  • +0

    私は私が従うかどうかわからない。どのようにしてravenWriterをRavenWriterBase <>かIRavenWriter <>として使うことができますか? –

    +0

    @BobHornそうですね。そこに 'RavenWriterBase <>'の知識はありません。代わりに 'IRavenWriterBase'(非汎用)を使用する必要があります。型のコンパイル時の知識はそこに存在しないので、キャストすることはできません。 – Aliostad

    +0

    ありがとうございます。私はちょうど私が動的を使用してInitialize()を呼び出す方法を示すために自分の質問を編集しました。私はそれがうまくいくと思います。 –

    1

    それはありませんランタイムTypeをコンパイル時ジェネリック型パラメータに変換するのは本当に難しいです。ちょうどあなたのオブジェクトを初期化する/作成するための新しいインターフェイスを導入:

     
    
    interface IRawenWriterFactory 
    { 
        object Create(); 
    } 
    
    class RawenWriterFactory<T> : IRawenWriterFactory 
    { 
        public object Create() 
        { 
        Expression<Func<IDataEntity, DateTime>> func = x => x.CicReadTime; 
    
        var ravenWriter = new RavenWriterBase<T>(); 
        ravenWriter.Initialize(60, func); 
    
        return ravenWriter; 
        } 
    } 
     
    

    は今ちょうどあなたがravenWriterを作成しただけのようdataEntityTypeでRawenWriterFactoryを作成し、非ジェネリックIRavenWriterFactoryインタフェースを介して、それを使用しています。

    ただし、デザインを変更すると簡単な解決策が得られる可能性があります。例えば。 Initializeメソッドをコンストラクタにすると、Activator.CreateInstanceパラメータとしてfuncを渡すことができ、初期化には汎用インタフェースを使用する必要はありません。

    関連する問題