2016-10-13 5 views
0

オブジェクトのプロパティをオブジェクトにマップするヘルパー関数を構築しています。このオブジェクトは、プロパティがバインドされているUIコンポーネントとその値を前後に変換する方法を知っています。ジェネリックコンバーターのマップをC言語で使用する方法#

プロパティ名(String型)を汎用のコンバータ(StringToBoolConverterなど)を含むModelFieldItemにマップするには、マップ自体が必要です。しかし、<?>オペレータの不足のために、私はJavaから慣れています. と書くことはできません。ここで、ModelFieldItemには情報タイプとコンバータ自体が含まれています。

結果、マップにModelFieldItemを追加したいが、タイプが異なる場合は、特定のタイプを追加する必要があります。 タイプパラメータとして既にdynamicまたはobjectを使用しようとしましたが、遅かれ早かれそれが動作しないポイントに達します。 C# - Multiple generic types in one listからトリックを使用して

私は、コンパイラが幸せになったが、私はいつもfalseに解決以下の条件

if (item is ModelFieldItem<dynamic, dynamic>) 
{ 
    ModelFieldItem<dynamic, dynamic> dynamicItem = (ModelFieldItem<dynamic, dynamic>)item; 

に私を導いた私のコンバータ・ロジックにアクセスするために型キャストを必要としていました。変換を開始する方法は、所望される、変換するためにどの種類、

EDIT

を知りません。ループを使用してプロパティを反復処理し、対応するコンバータを開始します。変換の時点でのキャスティングは、われわれがそれらを知ることができないので、異なるタイプでは実行できません。

私たちのコンバータは、先に述べたように、次のabstract class

public abstract class TypedConverter<A, B> 
{ 
    public abstract B convertFrom(A value); 

    public abstract A convertTo(B value); 
} 

から継承し、彼らは可能な限り簡単です、私は、Javaの背景から来たんだ、だから何私が達成したいことは大体のように見えますJavaの

private Map<String, ModelFieldItem<?,?>> converters = new HashMap<>(); 

に次と私は大体

converters.put("key", new Converter<String, Boolean>()); 
0のようにそれを使用します

これをC#でどのように達成できますか?

+0

(SetValueを介して)他のモデルのプロパティを設定するためにリフレクションを使用していますか?反射は通常 'オブジェクト'で動作するので、型安全性はあなたのものを買わない。つまり、基本的な 'ModelFieldItem'を基になる' Func 'デリゲートと共に使用することができます。 –

+0

また、すべてのプロパティに対して、または少なくともデフォルトの実装としてコンバータを指定する代わりに、 'Convert.ChangeType'を見てください。また、マッピングプロパティを専門とするAutomapperをチェックしたいかもしれません。 –

+0

@TravisParks:ご意見ありがとうございます。私たちはコンバータの型の安全性が必要ですa)インプリメンテーションをより明確にし、b)モデルに正しいタイプを設定し、リフレクションを通して適切なTypeを設定する必要がありますか、間違っていますか?デリゲートを使用するためのアイデアはいいです、私はそれを試してみます。 – Phe0nix

答えて

1

通常、この種の問題が発生した場合、ジェネリック型を必要としないクラスの抽象化を使用する必要があります。

ModelFieldItemに汎用パラメータのないインターフェイスを実装している場合は、それを使用できます。

var _dict = new Dictionary<String, IModelFieldItem>() 
{ 
    new Converter<string, bool>() // If it's implement IModelFieldItem 
}; 

(YouWillHaveToCastUnlessYouUseDynamicType)_dict[key].Convert("true"); 

そうでない場合は、別の方法は、あなたの辞書からの値にアクセスするとき、あなたはそれをキャストすることができ、objectまたはdynamicによりDictionary<String, ModelFieldItem>からModelFieldItemを置き換えることであろう。

var _dict = new Dictionary<String, object>() 
{ 
    new Converter<string, bool>() 
}; 

// You can avoid the cast too by using dynamic 
// But it will cost you some perf 
((Converter<string, bool>)_dict[key]).Convert("true"); 

希望するタイプがわかっている場合。ここで

var _dict = new Dictionary<String, object>() 
{ 
    new Converter<string, bool>() 
}; 

public void Convert<TToConvert, TConverted>(string key, TToConvert valueToConvert, out TConverted valueConverted) 
{ 
    valueConverted = (T)_dict[key].Convert(valueToConvert); 
} 

bool value; 
Convert("Key", "true", out value); 

あなたは何ができるかの他の例:あなたはそのような何かを行うことができます

public static void Convert<TToConvert, TConverted>(TToConvert valueToConvert, out TConverted valueConverted) 
    { 
     // You should put the dictionary outside of the method 
     // To avoid to instance it, each time you call this method 
     var dict = new Dictionary<Type, Func<object, object>>() 
     { 
      { typeof(Tuple<string, int>), x => int.Parse((string)x) }, 
      { typeof(Tuple<string, bool>), x => bool.Parse((string)x) } 
     }; 
     valueConverted = (TConverted)dict[typeof(Tuple<TToConvert, TConverted>)](valueToConvert); 
    } 

    static void Main(string[] args) 
    { 
     bool boolTest; 
     Convert("false", out boolTest); 
     Console.WriteLine(boolTest); 
     int intTest; 
     Convert("42", out intTest); 
     Console.WriteLine(intTest); 
     Console.ReadKey(); 
    } 

Obvisoulyをあなたが最初にしても、あなたのタイプを変換することができれば、あなたは試してみてください変換が成功した場合。最後にConvertを成功させるかどうかを判断するブール値を返します。
少なくとも、ご覧のとおり、変換を行うにはstring keyが必要でなく、興味があるかもしれません。 また、メソッドに渡すときに変数の型が正しいことを確認する必要があります。そうでない場合は、間違ったキーを検索します。


リフレクションソリューション:プロパティで

static void Main(string[] args) 
{ 
    object[] parameters = new object[] { "false", true }; 
    typeof(Program).GetMethod("Convert") 
    // Be sure that the types will create a valid key 
     .MakeGenericMethod(new Type[] { parameters[0].GetType(), parameters[1].GetType() }) 
    // Change null to your instance 
    // if you are not calling a static method 
     .Invoke(null, parameters); 
    // parameters[1] is an out parameter 
    // then you can get its value like that 
    Console.WriteLine(parameters[1]); 
    Console.ReadKey(); 
} 

、次のようになります:あなたがそのような何かを行うことができ、上記の方法で

object[] parameters = new object[] 
{ 
    propertyToRead.GetValue(objectToRead), 
    propertyToSet.GetValue(objectToSet) 
}; 

typeof(MapperObject).GetMethod("Convert") 
    .MakeGenericMethod(new Type[] 
     { 
      propertyToRead.PropertyType, 
      propertyToSet.PropertyType 
     }) 
    .Invoke(mapperInstance, parameters); 

propertyToSet.SetValue(objectToSet, parameters[1]); 

ます私はそれをコンパイルしようとしなかったので、少し調整する必要があります


私は別の解決策を与えることができるが、私はどちらも、あなたの相続アーキテクチャも、どのようにあなたのConverter作品が何であるかを知りません。

+0

' dynamic'は* HUGE *のパフォーマンスに影響します。 – Bauss

+0

ええ、私は知っています。私もそれらを避ける。しかし、とにかく、それはあまりにも問題に答えるかもしれません。 –

+0

@Bauss、次回は最低でも、私たちの投稿を完全に書き留めてから、downvotingすることができます。) –

関連する問題