假设一种方法决定应该使用哪种方法来转换值。
public static TTarget ConvertValue<TTarget>(object value)
{
Type t = typeof(TTarget);
if (t.IsEnum)
return ParseEnum<TTarget>(value);
else //if ...
return ...;
}
处理该值的一些方法具有带约束的泛型类型参数。
public static TEnum ParseEnum<TEnum>(object value)
where TEnum : struct
{
//do something
return ...;
}
编译器不允许使用此方法,因为类型TTarget
不一定是struct
,可以变为NULL
,因此不能用作TEnum
。< / p>
假设没有约束的泛型方法和带有附加约束的方法:
public void DoStuff<T>(T obj)
{
if (obj is IComparable && obj is ICloneable)
DoSpecialStuff<T>(obj);
}
public void DoSpecialStuff<T>(T obj)
where T : IComparable, ICloneable
{
}
这也行不通,因为(afaik)无法转换为多个接口。
是否可以重用泛型类型来调用具有其他约束的方法?
答案 0 :(得分:3)
您需要使用Reflection调用该方法 没有更好的方法。
您应该考虑调用非泛型方法(并将typeof(TTarget)
作为参数传递) - ParseEnum
不应该是通用的。
答案 1 :(得分:2)
As SLaks mentions,实现这一目标的唯一方法是使用反射。这是一种做法。 (委托缓存在字典中,以便后续调用相同类型不需要反射。)
public static TTarget ConvertValue<TTarget>(this object value)
{
Type t = typeof(TTarget);
if (t.IsEnum)
{
Delegate del = _delegateCache.GetOrAdd(t, t2 =>
Delegate.CreateDelegate(typeof(Func<object, TTarget>),
_parseEnumInfo.MakeGenericMethod(t2));
return ((Func<object, TTarget>)del)(value);
}
else // if ...
return ...;
}
private static readonly MethodInfo _parseEnumInfo =
typeof(YourParentClass).GetMethod("ParseEnum");
private static readonly ConcurrentDictionary<Type, Delegate> _delegateCache =
new ConcurrentDictionary<Type, Delegate>();
public static TEnum ParseEnum<TEnum>(object value)
where TEnum : struct, IComparable, IConvertible, IFormattable
{
// do something
return ...;
}
或者,为了匹配你的第二个例子:
public void DoStuff<T>(T obj)
{
if ((obj is IComparable) && (obj is ICloneable))
{
Delegate del = _delegateCache.GetOrAdd(typeof(T), t =>
Delegate.CreateDelegate(typeof(Action<T>),
this,
_doSpecialStuffInfo.MakeGenericMethod(t));
((Action<T>)del)(obj);
}
}
private static readonly MethodInfo _doSpecialStuffInfo =
typeof(YourParentClass).GetMethod("DoSpecialStuff");
private readonly ConcurrentDictionary<Type, Delegate> _delegateCache =
new ConcurrentDictionary<Type, Delegate>();
public void DoSpecialStuff<T>(T obj)
where T : IComparable, ICloneable
{
}
答案 2 :(得分:0)
如果对于每个感兴趣的接口,您定义具有“额外”通用参数T的版本,其继承通用接口和ISelf&lt; out T&gt; (我建议接口包含单个只读属性“self”,类型为T),并且如果每个感兴趣的类实现ISelf&lt; ItsOwnType&gt;,则,例如,的IFoo&LT; T&GT;继承自IFoo和T,需要实现IFoo和IBar的例程可以接受IFoo&lt; IBar&gt;类型的参数。如果传入的参数被称为X,则X将实现IFoo,X.Self将实现IBar。这种方法的美妙之处在于,实现以这种方式定义的任何接口组合的任何此类对象都可以类推,以任何顺序实现这些接口的任何组合。这种方法的一个弱点是,它假定对象将定义ISelf&lt; T&gt; .Self返回自己,但是没有真正保证这样的对象不会返回别的东西。