2014-03-04 40 views
0

我目前正在尋求建立動態類型轉換器,反映op_implicit表

例如,我可以很容易做到:

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

我已經看到了你可以看到表here,但我不知道是否有可能從反映它框架本身。

請注意,這不是一個真正的阻塞問題,如果不可能,我會從表中手動添加轉換器,但我顯然更喜歡將此動態構建(更乾淨,更容易出錯)。

回答

5

基本類型的運算符未在框架中定義 - 它們是CLI本身的一部分;基本上他們有自己的特別指示。沒有IL參與,沒有方法,因此MethodInfo沒有任何參考。

但是,如果你看看System.Decimal,你會發現運營商在框架本身中實現了「正義」。

(在略微類似的方式,string不聲明+運算符; C#中的用途+被轉換爲調用string.Concat。)

+0

好吧,那麼這就是IL操作符的所有conv套件。謝謝,將隨手冊添加,然後,不是一個biggie。 – catflier

0

當然喬恩是正確的。但是,您可以參考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 
     } 
    } 
}