【发布时间】:2012-04-13 15:36:31
【问题描述】:
我已经解决了几个小时的问题,我想我已经接近了。我正在开发一个应用程序,我们可以有 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 是一样的,我也不应该需要泛型接口。
【问题讨论】:
-
听起来像是对泛型的不当使用。当您发现自己需要基于不同类型运行不同的方法,但类型仅在运行时才知道时,您希望利用多态性。仿制药给你带来了什么?您能否在没有泛型的情况下按原样运行方法,即使用 IDataEntity?
-
我同意 mellamokb。但是,如果您设置了泛型,为什么不创建一个可以非泛型实例化的包装类。包装器应该有一个方法,该方法根据作为参数传入的类型返回 RavenWriterBase
的实例。然后,实例化包装器并以请求的类型作为参数调用方法。这将需要一个大的 switch 语句,但至少不需要 200 个单独的类。 -
您是否创建了其他不使用 IDataEntity for T 的表达式?还是 T 始终是 IDataEntity?如果 T 总是 IDataEntity,为什么要使用泛型?
-
@DavidCowden:好主意,实际上并没有那么难,因为使用我们一直使用的 T4 模板可以轻松实现这一点。
-
@mellamokb 我没有根据不同的类型运行不同的方法。我一定没有说清楚。我不明白你在哪里看到的。我想在每个实例上调用 Initialize() 和 Execute()。
标签: c# .net linq generics expression-trees