簡體   English   中英

在運行時使用通用接口創建通用類型

[英]Create Generic Type with Generic Interface at Run Time

我現在已經解決了幾個小時的問題,我想我很接近。 我正在開發一個應用程序,我們可以有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 ravenWriter = Activator.CreateInstance(ravenWriterType);
ravenWriter.Initialize(60);

我作弊了一點,因為我意識到每個IDataEntity的Func是相同的,所以沒有必要作為參數傳遞給Initialize()。 但是,至少現在我可以調用Initialize()。 但是現在Func是相同的,我也不需要通用接口。

我的解決方案是:

  • 創建IRavenWriter的非泛型接口
  • 使IRavenWriter<T>繼承自IRavenWriter
  • IRavenWriter保持ExecuteExecutionIntervalInSeconds
  • 使IRavenWriter具有Func<DateTime>並在您的IRavenWriter使用它
  • 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});

將運行時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;
  }
}

現在只需使用dataEntityType創建RawenWriterFactory就像您創建了ravenWriter並通過非泛型IRavenWriterFactory接口使用它一樣。

但是,如果您改變設計,可能會有更簡單的解決方案。 例如,如果將Initialize方法轉換為構造函數,則可以將func作為Activator.CreateInstance參數傳遞,並且根本不需要使用通用接口進行初始化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM