2016-06-17 18 views
0

多態性に使用する抽象基本クラスがあり、派生型を別の派生型に変換するメソッドを記述したいが、コンパイル時に派生型を知らない。私はリフレクションがこれを解決する正しい方法だと信じていますが、それを実装する正しい方法は何か分かりません。ここに私は現在立ち往生しています。実行時に未定義の派生型を変換する

Public Static BaseClass ConvertTo(BaseClass bc, Type type) { 
    //bc is currently DerivedClass1 which implements IConvertable 
    //type is currently DerivedClass2 
    //Trying to convert DerivedClass1 to DerivedClass2 
    return (BaseClass)ChangeType(bc, type); 
} 

この方法はDerivedClass2にDerivedClass1を変換しますが、それは私が実装しなければならない15個の不要な方法が付属していますので、私はそれを動作させるために、私はに不満だこれは、DerivedClass1ためIConvertableインタフェースを実装する必要がありました。

これを解決するためのよりエレガントな方法があります。これは、コンパイル時のキャストに近いものですか? DerivedClass1にDerivedClass2キャスト演算子があるかどうかによって、メソッドが成功するか、実行時例外がスローされる場所。次のようなものがあります。

Public Static BaseClass ConvertTo(BaseClass bc, Type type) { 
    //First down cast it to bc, then sideways cast it to type. 
    return (type)((bc.GetType())bc) 
} 
+0

これで、ユーザー定義の変換で作業を行い、それを見つけてリフレクションで実行したいだけですか? –

+0

類似の構造のコピーを作成しようとしていませんか?あなたが何をしようとしているものであれ、Automapperはもっと役に立つかもしれない – Arjang

答えて

3

ユーザー定義の変換演算子でのリフレクションを求めているようです。あなたは、公的な静的メソッドを求めて、op_explicitまたはop_implicitという名前のフィルタにフィルタリングし、適切なパラメータと戻り値の型を持ち、MethodAttributes.SpecialNameを含めて、リフレクションを使用してそれらを得ることができます。次に、通常通りメソッドを呼び出します。ここで

は、私はすぐにホイップきたいくつかのサンプルコードです - あなたも、堅牢性のためのより多くのチェックを追加したい派生型やベースの種類などからの変換が含まれ...しかし、それはスタートだことがあります。

using System; 
using System.Linq; 
using System.Reflection; 

class Foo 
{ 
    public int Value { get; set; }   
    public static explicit operator Bar(Foo x) => new Bar { Value = x.Value }; 
    public static explicit operator Foo(Bar x) => new Foo { Value = x.Value }; 
} 

class Bar 
{ 
    public int Value { get; set; } 
} 

class Test 
{ 
    static void Main() 
    { 
     var foo = new Foo { Value = 10 }; 
     var bar = Convert<Bar>(foo); 
     Console.WriteLine(bar.Value); 
     foo = Convert<Foo>(bar); 
     Console.WriteLine(foo.Value);   
    } 

    public static T Convert<T>(object source) 
    { 
     var conversion = FindConversion(source.GetType(), typeof(T)); 
     if (conversion == null) 
     { 
      throw new InvalidOperationException("No conversion found"); 
     } 
     return (T) conversion.Invoke(null, new[] { source }); 
    } 

    private static MethodInfo FindConversion(Type fromType, Type toType) 
    { 
     var expectedParameterTypes = new[] { fromType }; 
     var methods = from type in new[] { fromType, toType } 
         from method in type.GetMethods(BindingFlags.Public | BindingFlags.Static) 
         where method.Name == "op_Explicit" || method.Name == "op_Implicit" 
         where (method.Attributes & MethodAttributes.SpecialName) != 0 
         where method.ReturnType == toType 
         where method.GetParameters() 
            .Select(p => p.ParameterType) 
            .SequenceEqual(expectedParameterTypes) 
         select method; 
     return methods.FirstOrDefault(); 
    } 
} 
+0

ありがとう!これはまさに私が探していたものでした。 – Brian

関連する問題