[英]Generic query with interface as a generic parameter
So I've been fighting against generics lately and don't quite know how to solve this one. 因此,最近我一直在与泛型作斗争,并且不太了解如何解决这一问题。
Basically I have a generic query framework defined as IRxQuery<T>
. 基本上,我有一个通用查询框架,定义为
IRxQuery<T>
。 My basic model follows one rule: T needs to be an instance type. 我的基本模型遵循一个规则:T必须是实例类型。 Here is the implementation header:
这是实现标头:
public class RxQuery<T> : IRxQuery<T>
where T : IQueryableObject
One of the notable methods in this class is the Get
method, which will deserialize the object got by the query into a T object. 此类中值得注意的方法之一是
Get
方法,它将查询获得的对象反序列化为T对象。 The method kinda looks like that: 该方法有点像这样:
protected virtual T Get(IDeserializableObject row)
{
var value = Activator.CreateInstance<T>();
// fill value
return value;
}
Now, I would like to upgrade my query so it would be working with an interface. 现在,我想升级我的查询,以便它可以与接口一起使用。 I am facing the current problem: I have an
ISomething
interface, implemented by ObjectA
and ObjectB
. 我正面临当前的问题:我有一个由
ObjectA
和ObjectB
实现的ISomething
接口。 I'd have a case where the query could be any of them and I am trying to fix it, without going adding inheritance. 我有一种情况,其中查询可以是其中的任何一个,而我试图修复它,而无需添加继承。 So I was trying something like:
所以我在尝试类似的东西:
IRxQuery<ISomething> query;
if (isObjectA)
{
query = new RxQuery<ObjectA>();
}
else
{
query = new RxQuery<ObjectB>();
}
And of course, you know that won't compile. 当然,您知道那不会编译。 The only solution I thought about so far would be to add a property to the
IRxQuery
type looking like: 到目前为止,我想到的唯一解决方案是向
IRxQuery
类型添加一个属性,如下所示:
public Type InstanceType{ get; set; }
And then update the Get method to this: 然后将Get方法更新为此:
protected virtual T Get(IDeserializableObject row)
{
T value = (T)Activator.CreateInstance(typeof(InstanceType))
}
What approach would you advise me to use to fix this problem? 您会建议我使用哪种方法来解决此问题?
Thank you! 谢谢!
It sounds like you're trying to make this work: 听起来您正在尝试进行以下工作:
class Program {
static void Main(string[] args) {
//compile error: ISomething must be non-abstract with public
// parameterless constructor
RxQuery<ISomething> something = new RxQuery<ISomething>();
}
}
interface ISomething { };
interface IRxQuery<T> { }
public class RxQuery<T> : IRxQuery<T> where T:new() /*, IDeserializableObject*/ {
//Factory Method Pattern
protected virtual T Get(/*IDeserializableObject row*/) { return new T(); }
}
Get
is a factory method and cannot instantiate an interface using new()
. Get
是一种工厂方法,无法使用new()
实例化接口。 Even if you made T
covariant ( IRxQuery<out T>
), you're no closer to it working. 即使您使
T
协变量( IRxQuery<out T>
),您也离它越来越近。 Your proposed solution of using Activator.CreateInstance
(reflection) and having the Type information returned from IRxQuery
might work, but regardless it's a poor solution in my opinion (it forfeits some compile-time checks, and requires reflection (obfuscation, if ever needed, could cause this code to crash)). 您提出的使用
Activator.CreateInstance
(reflection)并从IRxQuery
返回Type信息的解决方案可能可行,但是我认为这不是一个糟糕的解决方案(它放弃了一些编译时检查,并且需要进行反射(混淆,如果需要,可能导致此代码崩溃))。
If T
must be able to be an interface
, then my suggestion is to find a new design such that RxQuery<T>
does not need to construct an object of type T
. 如果
T
必须能够成为interface
,那么我的建议是找到一个新设计,使得RxQuery<T>
不需要构造T
类型的对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.