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にカーソルを合わせると、オブジェクトが正常に表示されます。

ここに画像の説明を入力してください

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

アップデート:

dynamicキーワードを使用することを考えたところ、これは機能します。

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

Funcが各IDataEntityで同じであることに気付いたので、少しだましました。そのため、Initialize()にパラメーターとして渡す必要はありませんでした。ただし、少なくとも今はInitialize()を呼び出すことができます。しかし、Funcが同じになったので、ジェネリックインターフェイスも必要ありません。

4

2 に答える 2

2

私の解決策は次のとおりです。

  • の非ジェネリックインターフェイスを作成するIRavenWriter
  • からIRavenWriter<T>継承するIRavenWriter
  • 維持ExecuteExecutionIntervalInSecondsIRavenWriter
  • IRavenWriter持っFunc<DateTime>て、あなたの作家でそれを使用してください
  • Initializeに移動IRavenWriter<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});
于 2012-04-13T15:54:20.823 に答える
1

ランタイムTypeをコンパイル時のジェネリック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;
  }
}

ここで、作成RawenWriterFactoryしたのと同じようにdataEntityTyperavenWriterを使用して作成し、非汎用IRavenWriterFactoryインターフェイスを介して使用します。

ただし、設計を変更する場合は、より簡単な解決策がある可能性があります。たとえば、Initializeメソッドをコンストラクターに変えると、funcをActivator.CreateInstanceパラメーターとして渡すことができ、初期化にジェネリックインターフェイスを使用する必要はまったくありません。

于 2012-04-16T09:03:30.190 に答える