我正在实现一个通用接口(特别是iqueryprovider)。在某些时候,我被迫返回一个通用结果,我需要从一些内部接口获取:
public TResult Execute<TResult>(...) {
return something.Foo<TResult>();
}
其中something.Foo是
public T Foo<T>() where T: MyBaseClass, new() {
...
}
这当然会爆炸,因为外部定义的TResult与内部定义的T没有相同的类型限制。问题是:有没有办法让TResult适合Foo?我可以以某种方式明确测试这两个条件并强制类型变量吗?
答案 0 :(得分:2)
您可以尝试这样的事情:
public TResult Execute<TResult>(...)
{
if (typeof(TResult) is MyBaseClass)
{
Type mytype = typeof(TResult);
MethodInfo method = typeof({TypewhereFoo<>IsDeclared}).GetMethod("Foo");
MethodInfo generic = method.MakeGenericMethod(myType);
return (TResult)generic.Invoke(this, null);
}
else
{
// Throw here
}
}
答案 1 :(得分:1)
不。如果TResult对它没有约束,那么它可以是任何旧的东西。如果你的帮助方法不能采取任何旧的东西,那么你需要一个更好的帮助方法。界面要求您提供比助手提供的服务更多的服务,因此,您将不得不完成提供该服务的工作。
答案 2 :(得分:0)
您必须将类型限制添加到通用方法中:
public TResult Execute<TResult>(...) where TResult: MyBaseClass, new() {
return something.Foo<TResult>();
}
答案 3 :(得分:0)
哎哟......你有问题。没有办法调用something.Foo(),因为你没有兼容的类型。你可以通过创建一个兼容调用Foo()然后'解包'的“包装”类型来“破解”:
class MyNastyFix<T> : MyBaseClass
{
public T Unwrap()
{
//assert that T has the correct base type
if (!typeof(T).IsSubclassOf(typeof(MyBaseClass)))
throw new ArgumentException();
//must use reflection to construct
T obj = (T)typeof(T).InvokeMember(null, BindingFlags.CreateInstance, null, null, null);
//cast to a type of MyBaseClass so we can copy our values
MyBaseClass c = (MyBaseClass)(object)obj;
c.SomeValue = this.SomeValue;
return obj;
}
}
public static TResult Execute<TResult>()
{
return something.Foo<MyNastyFix<TResult>>().Unwrap();
}
更新:如果有效,反思答案可能是更好的方法。
答案 4 :(得分:0)
更改Foo以在运行时检查约束:
public T Foo<T>() {
if (!typeof(T).IsAssignableFrom(typeof(MyBaseClass))
|| !typeof(T).GetConstructor(...))
throw new System.NotImplementedException();
...
}
在编译时检查通用约束,因此它们不能基于运行时条件。