[英]How to cast an object as having a public parameterless constructor to respect a : new() constraint?
Is it possible at all to check if a type has a parameterless constructor, in order to cast it and call a method which requires a parameterless constructor with the : new()
constraint? 是否可以检查类型是否具有无参数构造函数,以便进行强制转换并调用需要使用无参数构造函数且带有
: new()
约束的方法?
Being only able to only check that a type as a public parameterless as answered here would not be enough as it would not allow calling the target methods. 仅能检查此处确认为无参数的公共类型是不够的,因为它不允许调用目标方法。
The objective is to have the following logic, where IInteresting
objects do not implement a public parameterless constructor and need to be converted before calling Save1
: 目的是要具有以下逻辑,其中
IInteresting
对象不实现公共的无参数构造函数,需要在调用Save1
之前进行转换:
public interface IInteresting { }
public void Save<T>(T o) {
var oc = o as (new()); /* Pseudo implementation */
if (oc != null) {
this.Save1(oc);
}
else {
var oi = o as IInteresting;
if (oi != null) {
this.Save2(oi);
}
}
}
private void Save1<T>(T o) where T : new() {
//Stuff
}
private void Save2<T>(IInteresting o) {
//Stuff to convert o to a DTO object with a public parameterless constructor, then call Save1(T o)
}
Of course if I could make Save1
and Save2
share the same signature that would solve the issue, but I cannot find a way to do so as the following will not compile (in Routine
, Save
will call the first implementation instead of the second): 当然,如果我可以使
Save1
和Save2
共享可以解决该问题的相同签名,但是由于以下内容无法编译(在Routine
, Save
将调用第一个实现而不是第二个实现),因此我无法找到一种方法:
public void Routine<T>(T o) {
var oi = o as IInteresting;
if (oi != null) {
this.Save(oi);
}
}
private void Save<T>(T o) where T : new() {
//Stuff
}
private void Save<T>(IInteresting o) {
//Stuff to convert o to a DTO object with a public parameterless constructor, then call Save(T o)
}
Based on your comments, I imagine you have an object of an unknown type that you want to pass to a generic function that requires the passed-over object to be of the generic type argument, which has to have a parameterless constructor. 根据您的评论,我想您有一个要传递给泛型函数的未知类型的对象,该泛型函数要求传递的对象具有泛型类型参数,该参数必须具有无参数构造函数。 Hence, for the time being, we can assume that your function
Save1<T>(T)
from your question is that function, not written by you, not possible to be changed. 因此,就目前而言,我们可以假定问题中的函数
Save1<T>(T)
是该函数,不是您编写的,也不可能被更改。
A solution to this would be to make the call by using reflection: 一种解决方案是使用反射进行调用:
MethodInfo
of the method you are trying to call by using Type.GetMethod
. Type.GetMethod
查找要尝试调用的方法的MethodInfo
。 MethodInfo
of the method for your parameterless-constructor-type by specifying type arguments with MakeGenericMethod
. MakeGenericMethod
指定类型实参,为您的无参数构造函数类型构造方法的MethodInfo
。 MethodInfo.Invoke
method . MethodInfo.Invoke
方法来调用该方法 。 Another possible solution, depending on what you do inside private void Save<T>(T o) where T : new()
is to use ICloneable
interface. 另一个可能的解决方案,取决于您在
private void Save<T>(T o) where T : new()
内所做的工作private void Save<T>(T o) where T : new()
将使用ICloneable
接口。 Or introduce yours (as I've said, it depends on Save
's contents): 或介绍您的(如我所说,这取决于
Save
的内容):
interface IConstructible
{
object Construct();
}
And have: 并具有:
private void Save1<T>(T o) where T : ICloneable {
Of course this is just a workaround - OR Mapper's answer gives the only direct solution. 当然,这只是一种解决方法- 或Mapper的答案给出了唯一的直接解决方案。
using System.Reflection;
public static class Generics {
public static void T0<T> ( T obj ) where T : new () {
Console.WriteLine ( "{0} {1}", obj, obj.GetType () );
}
public static void T1<T> ( T obj ) {
MethodInfo mi = GenericMethodInfo ( typeof ( Generics ), "T0", typeof ( T ) );
mi.Invoke ( null, new object[] { obj } );
}
public static MethodInfo GenericMethodInfo ( Type classType, string methodName, Type genericType ) {
return classType.GetMethod ( methodName ).MakeGenericMethod ( genericType );
}
}
Generics.T0 ( 123 );
Generics.T1 ( 123 );
// Impossible.. Generics.T0 ( "12345" );
Generics.T1 ( "12345" );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.