c# - 在运行时创建具有通用接口(interface)的通用类型

标签 c# .net linq generics expression-trees

我已经处理一个问题几个小时了,我想我已经接近了。我正在开发一个应用程序,我们可以在其中使用 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);

我有点作弊,因为我意识到每个 IDataEntity 的 Func 都是相同的,因此没有必要将其作为参数传递给 Initialize()。但是,至少现在我可以调用 Initialize()。但既然 Func 是一样的,我也不应该需要通用接口(interface)。

最佳答案

我的解决方案是:

  • 创建IRavenWriter 的非通用接口(interface)
  • 制作IRavenWriter<T>继承自 IRavenWriter
  • 保留 ExecuteExecutionIntervalInSecondsIRavenWriter
  • 制作IRavenWriterFunc<DateTime>并在你的作家中使用它
  • 移动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});

关于c# - 在运行时创建具有通用接口(interface)的通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10143899/

相关文章:

c# - log4net 日志文件在哪里?

c# - 查询字符串模型绑定(bind) ASP.NET WebApi

c# - 我可以保存控制台窗口的缓冲区或内容以备将来使用吗?

c# - 在 Renci SSH.NET 中启动自定义 SSH 子系统(相当于 ch.ethz ssh2.Session.StartSubSystem())

c# - 无法向 ServiceControl 注册端点启动

.NET DataSet 实现底层

c# - 为linq查询结果添加索引

c# - C# 中不允许检查特殊字符

c# - 将 LINQ 的 Zip 与不返回值的闭包一起使用

c# - 使用 LINQ 获取在列表中出现一次的元素的计数