我目前正在寻求建立动态类型转换器,
例如,我可以很容易做到:
public struct Tester
{
public int Hello;
public static implicit operator int(Tester d)
{
return d.Hello;
}
public static implicit operator float(Tester d)
{
return d.Hello;
}
}
然后
typeof(Tester).GetMethods()
将返回我隐式转换的MethodInfo。
但是,如果我这样做:
typeof(int).GetMethods()
这将不返回任何op_implicit
我已经看到了你可以看到表在这里 ,但我想知道是否有可能从框架本身反映它。
请注意,这不是一个真正的阻塞问题,如果它是不可能的,我会从表中手动添加转换器,但我显然希望有此动态生成(清洁且不易出错)。
对于原始类型的运营商在框架中没有定义 - 他们的CLI本身的一部分; 他们有自己的特殊说明,基本上是这样。 有没有IL参与,没有方法,所以没有一个MethodInfo
引用。
如果你看一下System.Decimal
,但是,你会为在框架本身实现“公正”找到经营者。
(在一个稍微类似的方式, string
不声明+
算子;用途+
C#中被转换为调用string.Concat
。)
当然乔恩是正确的。 但是,你看看它可能是有用的System.Linq.Expressions.Expression
类(尤其是Convert
方法)。 举例来说,一个可以快速构建是这样的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Tests
{
static class ConvertTest
{
// conceptual point
static Func<TInput, TOutput> CreateConvertFunc<TInput, TOutput>()
{
var source = Expression.Parameter(typeof(TInput), "source");
// the next will throw if no conversion exists
var convert = Expression.Convert(source, typeof(TOutput));
var method = convert.Method;
if (method != null)
{
// here is your method info
}
else
{
// here is the case of primitive types
// unfortunately it would not help you, because it's resolved when you call Complile.
// but you can take a look at reference implementation how they handle it
}
return Expression.Lambda<Func<TInput, TOutput>>(convert, source).Compile();
}
// cache
struct ConverterFunc<TInput, TOutput>
{
public static readonly Func<TInput, TOutput> Instance = CreateConvertFunc<TInput, TOutput>();
}
// fluent accessor
struct ConvertSource<T>
{
public T source;
public U To<U>()
{
try { return ConverterFunc<T, U>.Instance(source); }
catch (TypeInitializationException e) { throw e.InnerException; }
}
}
static ConvertSource<T> Convert<T>(this T source) { return new ConvertSource<T> { source = source }; }
// test
struct Wrapper<T>
{
public T Value;
public static implicit operator Wrapper<T>(T source) { return new Wrapper<T> { Value = source }; }
public static implicit operator T(Wrapper<T> source) { return source.Value; }
}
class A { }
class B : A { }
static void Main(string[] args)
{
var v0 = 1;
var v1 = v0.Convert().To<byte>();
var v2 = v1.Convert().To<double>();
var v3 = v2.Convert().To<decimal>();
var v4 = v3.Convert().To<Wrapper<decimal>>();
var v5 = v4.Convert().To<decimal?>();
var v6 = v5.Convert().To<int>();
var v7 = Enumerable.Empty<B>().Convert().To<IEnumerable<A>>();
var v8 = v7.Convert().To<int>(); // exception
}
}
}