我现在已经解决了几个小时的问题了,我觉得我很接近。我正在开发一个应用程序,我们可以有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指定一个类型&lt;&gt;我还不知道:
var ravenWriter = Activator.CreateInstance(ravenWriterType) as IRavenWriter<>;
如果我将鼠标悬停在ravenWriter上,我就成功拥有了我的对象:
但现在我需要能够以通用的方式使用它。我怎么能这样做?
更新
我只想到使用动态关键字,这有效:
dynamic ravenWriter = Activator.CreateInstance(ravenWriterType);
ravenWriter.Initialize(60);
我作弊了一点因为我意识到每个IDataEntity的Func是相同的,所以没有必要作为参数传递给Initialize()。但是,至少现在我可以调用Initialize()。但是现在Func是相同的,我也不需要通用接口。
答案 0 :(得分:2)
我的解决方案是:
IRavenWriter
IRavenWriter<T>
继承自IRavenWriter
Execute
和ExecutionIntervalInSeconds
保留在IRavenWriter
IRavenWriter
拥有Func<DateTime>
并在您的作家中使用Initialize
移至IRavenWriter<T>
例如:
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});
答案 1 :(得分: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;
}
}
现在只需使用dataEntityType创建RawenWriterFactory
,就像创建ravenWriter
一样,并通过非通用的IRavenWriterFactory接口使用它。
但是,如果您改变设计,可能会有更简单的解决方案。例如。如果你将Initialize方法转换为构造函数,你将能够将func作为Activator.CreateInstance参数传递,你根本不需要使用通用接口进行初始化。