正如其他答案所述,您不能这样做,因为您正在尝试将运行时转换应用于编译时转换操作。
如果您dynamic
因为不想使用 .NET 4.0 的 DLR 而想避免,您可以使用反射自己找到转换运算符。但是,无法评论您的特定应用程序的性能:
public static TOutgoing Convert<TOutgoing>(object obj)
{
Type incomingType = obj.GetType();
MethodInfo conversionOperator = null;
foreach(var method in incomingType.GetMethods(BindingFlags.Static | BindingFlags.Public))
{
if (
method.Name == "op_Explicit" && //explicit converter
method.ReturnType == typeof(TOutgoing) && //returns your outgoing ("Point") type
method.GetParameters().Length == 1 && //only has 1 input parameter
method.GetParameters()[0].ParameterType == incomingType //parameter type matches your incoming ("float2D") type
)
{
conversionOperator = method;
break;
}
}
if (conversionOperator != null)
return (TOutgoing)conversionOperator.Invoke(null, new object[]{obj});
throw new Exception("No conversion operator found");
}
或者对于带有 LINQ 的 .NET 3.5:
public static TOutgoing Convert<TOutgoing>(object obj)
{
Type incomingType = obj.GetType();
var conversionOperator = incomingType.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m => m.Name == "op_Explicit")
.Where(m => m.ReturnType == typeof(TOutgoing))
.Where(m => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == incomingType)
.FirstOrDefault();
if (conversionOperator != null)
return (TOutgoing)conversionOperator.Invoke(null, new object[]{obj});
throw new Exception("No conversion operator found");
}
用法:
float2D V = new float2D(1, 1);
Point P = Point.Empty;
P = Convert<Point>(V); //passes
P = Convert<Point>((V as object)); //passes
如果您希望通过隐式运算符进行转换,也可以添加“op_Implicit”。
如果要避免反射,另一种选择是预先注册转换函数、一些转换和类型查找以确定要使用的转换运算符。
需要注意的是,这里的解决方案有几个问题(线程安全、假设存在转换函数、注册冲突/重复转换函数会引发错误),因此请自行承担风险或将其用作根据您的需要进行修改的指南。
基本要点是定义一个简单的转换器来包装转换函数本身:
public interface IConverter
{
object Convert(object incomingObject);
}
public class Converter<TIncoming, TOutgoing> : IConverter
{
private Func<TIncoming, TOutgoing> ConversionFunction;
public Converter(Func<TIncoming, TOutgoing> conversionFunction)
{
this.ConversionFunction = conversionFunction;
}
public object Convert(object incomingObject)
{
TIncoming typedIncomingObject = (TIncoming)incomingObject;
return ConversionFunction(typedIncomingObject);
}
}
然后是一个可以注册这些转换的实用程序:
public static class ConversionUtility
{
private static Dictionary<Type, Dictionary<Type, IConverter>> Converters = new Dictionary<Type, Dictionary<Type, IConverter>>();
public static void RegisterConversion<TIncoming, TOutgoing>(Func<TIncoming, TOutgoing> conversionFunction)
{
if (!Converters.ContainsKey(typeof(TIncoming)))
{
Converters[typeof(TIncoming)] = new Dictionary<Type, IConverter>();
}
Converters[typeof(TIncoming)].Add(typeof(TOutgoing), new Converter<TIncoming, TOutgoing>(conversionFunction));
}
public static TOutgoing Convert<TOutgoing>(object obj)
{
Type incomingType = obj.GetType();
IConverter converter = Converters[incomingType][typeof(TOutgoing)];
return (TOutgoing)converter.Convert(obj);
}
}
为了使用,首先您必须注册您希望在您的应用程序中使用的转换函数(最好在您的应用程序启动时执行注册以避免线程问题):
ConversionUtility.RegisterConversion((float2D obj) => (Point)obj);
然后你的转换用法:
float2D V = new float2D(1, 1);
Point P = Point.Empty;
P = ConversionUtility.Convert<Point>(V); //passes
P = ConversionUtility.Convert<Point>((V as object)); //passes
对于您的特定应用程序使用情况,不确定其中一个的性能。第一个示例更灵活一些,因为它在运行时执行检查,您不必预先注册您希望使用的转换。第二个可能会更稳定一些,因为您只注册您希望使用的转换并且没有反射,只是转换和字典查找。