我正在与两个第三方图书馆合作,并在解决这一特定问题的方式上绞尽脑汁。我正在实现一个接口,它将传递类型为object
的对象,并且在大量调用中,我需要将它们传递给一个泛型方法,该方法需要一个具有类和new()
约束的类型定义
我知道我通过的任何对象都会遇到这些约束,但据我所知,我没有简单的方法可以指定一个对象满足这些条件的泛型方法。接口不能指定构造函数的约束,并且不允许抽象类作为泛型方法的类型参数。
在这种情况下传入的对象是由我知道和控制的,但是两个Delete方法的签名都无法修改。理想情况下,我只能实现一个保证无参数构造函数标准的接口,但这似乎不是一个选项。
这是我正在谈论的一个例子:
public void Delete(object toDelete) {
_repo.Delete(toDelete) // signature here is _repo.Delete<T>(T obj) where T : class, new()
}
为了给出一些背景知识并希望解释一下 - “删除”调用是ADO.NET数据服务中IUpdatable
的实现,而_repo.Delete<T>
调用来自SubSonic
。我有一个DataContextProvider
类将为我通过模型公开的每个类处理这些请求(以及其他类似的请求),因此直接转换为特定类是不可行的。我可以保证类总是类,并且有一个无参数构造函数,但是我不能说DataContext
只有一组固定的类可以传递下来 - 理想情况下我喜欢{{1}无需修改即可使用新类。
答案 0 :(得分:3)
您需要使用反射,您需要获取方法的MethodInfo对象以在您的存储库上调用,并动态调用它。
请注意,可能有一种更简单的方法可以做到这一点,但听起来你已经尝试过这个,否则这将是明显的解决方案。
由于你的“_repo”变量必须属于特定类型,例如Repository<Employee>
,你或许可以像这样投出它?
_repo.Delete(toDelete as Employee);
// or
_repo.Delete((Employee)toDelete);
或者,如果它是通用的:
_repo.Delete(toDelete as T);
如果这不是一个选项,由于你没有显示的代码,你需要求助于反思。
以下是示例:
using System;
using System.Reflection;
namespace ConsoleApplication14
{
public class Program
{
static void Main(string[] args)
{
Dummy d = new Dummy();
EntityType e = new EntityType();
d.Delete(e);
Console.In.ReadLine();
}
}
public class EntityType
{
public EntityType()
{
}
}
public class Dummy
{
private Repository<EntityType> _repo = new Repository<EntityType>();
public void Delete(object toDelete)
{
Type t = _repo.GetType();
Type genericType = t.GetGenericArguments()[0];
MethodInfo mi = t.GetMethod("Delete",
BindingFlags.Public | BindingFlags.Instance,
null, new Type[] { genericType }, new ParameterModifier[0]);
// _repo.Delete(toDelete);
mi.Invoke(_repo, new Object[] { toDelete });
}
}
public class Repository<T>
where T: class, new()
{
public void Delete(T value)
{
Console.Out.WriteLine("deleted: " + value);
}
}
}
答案 1 :(得分:2)
我知道我通过的任何物体都会遇到这些限制
它是一种公共方法。您不必担心您传入的任何对象。您必须担心任何人传入的任何对象。
如果你知道对象符合这些约束,你还知道对象是什么类型的吗?如果是这样,那么只需将其转换为该类型。
答案 2 :(得分:1)
我认为这会重复您已经知道的内容,但如果您真的无法改变其中任何一种Delete
方法,那么您就会陷入困境。
外部方法采用普通object
作为参数,内部方法需要T
参数,其中T
符合class, new()
约束。不幸的是,这两者无法在不做任何改动的情况下进行调和。
答案 3 :(得分:0)
您可以使用GetConstructors方法的反射来验证该类型是否具有无参数构造函数。这是你对new()约束的意思吗?