2017-01-30 11 views
0

タイトルは少し誤解を招くかもしれませんが、適切に言い方をする方法がわからないので、誰かがより良いタイトルを知っている場合は編集してください。クラス名をジェネリック型に変更します

ReadMessage)から派生しなければならないジェネリック型を取る方法があります。 そのように今私は、すべてがMessageBaseから継承したクラス名のリストを持っている:

messageBaseNames = { 
    { 1 : "MyMessageBase01" }, 
    { 2 : "MyMessageBase02" }, 
    { 3 : "AnotherMessageBase" } 
} 

次のようにReadMessage方法が通常使用されている:

public Dictionary<int,string> messageBaseNames = new Dictionary<int,string>(); 

は私の辞書はこのようになりますと言うことができます

public void ProcessMessageBase(NetworkMessage netMsg) { 
    var msg = netMsg.ReadMessage<MyMessageBase01>(); 
} 

これらの文字列表現をReadMessageジェネリック型に渡すことはできますか? netMsgにはshortの値があるので、どの文字列が正しいかわかります。ただ、添加物として

が、これはReadMessageの署名である:私は、単一の機能に集約したいと異なるネットワークメッセージの束を送信してい

を:

そして、明確化のためpublic TMsg ReadMessage<TMsg>() where TMsg : MessageBase, new();その方法から頒布する。そのためには、異なるMessageBaseタイプに対応するために、ReadMessage関数を動的にする必要があります。

+1

それはあなたのために大丈夫でしょうか? – NineBerry

+1

[リフレクトを使用して汎用メソッドを呼び出すにはどうすればよいですか?](http://stackoverflow.com/questions/232535/how-do-i-use-reflection-to-call-a-generic-method) – NineBerry

+0

@NineBerryいいえ、残念ながら、それは具体的なタイプでなければなりません。 – ShitakeOishii

答えて

0

@ティムの答えは、正しい方向、すなわち:How do I use reflection to call a generic method?C#:System.Reflection.MethodInfo cause : (Object does not match target type)を指摘しました。

問題を解決するコードスニペット:その後、あなたの例では、 `msg`variableは` MessageBase`代わりの具体的な種類を入力したとき

// Type.EmptyTypes is very crucial, because there are two methods with 
// the same `ReadMessage` name. The one that doesn't take parameters 
// was the needed one. 
MethodInfo method = typeof(NetworkMessage).GetMethod ("ReadMessage",Type.EmptyTypes,null); 
MethodInfo generic = method.MakeGenericMethod (*messageBaseTypes*); 

// In the referred thread `this` was passed instead of `netMsg` 
// However, an instance of the object is needed, else 
// a `TargetException : Object does not match target type` is thrown. 
var msg = generic.Invoke (netMsg, null); 
0

あなたが望むものに合ったものがありますか?

class Program { 
    static void Main(string[] args) { 
     var method = typeof(SomeClass).GetMethod("ReadMessage"); 
     var readMessage = method.MakeGenericMethod(System.Reflection.Assembly.GetExecutingAssembly().GetTypes().First(p => p.Name == "MyMessageBase01")); 

     var o = new SomeClass(); 

     Console.WriteLine(readMessage.Invoke(o, null)); 
    }   
} 

public class SomeClass { 
    public string ReadMessage<T>() { 
     return typeof(T).FullName; 
    } 
} 

public class MyMessageBase01 { 
} 

これは)「MyMessageBase01」という名前あなたの現在のアセンブリの最初のクラスを見つけて、ReadMessage(のための方法を構築するためにそれを使用します。

プロダクションで使用するには、その名前の最初の型を見つけるよりも賢明になりたいと思うし、文字列を辞書に型参照として格納して、すべての型を反映させる必要はありません毎回組立。

+0

'typeof(ReadMessage <>)'を実行できません。 'NetworkMessage'クラスの公開関数なので、私は想定しています。 – ShitakeOishii

+0

リフレクションを使用してジェネリックメソッドを呼び出す方法と、ジェネリッククラスを構築するのではなく名前でタイプを見つける方法を紹介するために、私の例を更新しました。 – Tim

+0

これは私が必要としていた100%ではありませんでしたが、正しい方向に私を指摘しました。私は私がそれをやった方法を示すために自分の答えを投稿します。 – ShitakeOishii

1

辞書の唯一の目的は、指定された整数値に応じて適切なReadMessageメソッドを呼び出すことである場合は、代わりに関数の辞書を使用します。我々はまだ(ActionFuncを使用して

Func<NetworkMessage, MessageBase> reader; 
if (messageBaseReaders.TryGetValue(msgId, out reader)) 
{ 
    var msg = reader(netMsg); 
} 
else 
{ 
    // Desired error handling... 
} 

は、C#でジェネリックをはるかに柔軟性を可能にする:

public dictionary<int, Func<NetworkMessage, MessageBase>> messageBaseReaders; 

それから私は、私はそのようにそれらを使用することになりその後

messageBaseReaders.Add(1, (nm) => nm.ReadMessage<MyMessageBase01>()); 
messageBaseReaders.Add(2, (nm) => nm.ReadMessage<MyMessageBase02>()); 
messageBaseReaders.Add(3, (nm) => nm.ReadMessage<AnotherMessageBase>()); 

でそれらを初期化します比較的簡単で効率的なコード)。その場合、あなたは反射を必要としません。

それ以外の場合は、反射が必要な場合は、Timの回答を参照できます。

また、依存性注入フレームワークを使用することもできます。

ベストソリューションは、実際のコードと今後必要になるものによって異なります。 クラスにはpublic virtual ReadMessageメソッドがあり、作成目的でのみ使用することをお勧めします。そうすれば、SRPの原則を尊重し、コードをより保守性と拡張性にすることができます。

+0

良いアイデアですが、私はここで同じ問題に遭遇していませんか?私はコンパイル時にクラス名を知らない。ディクショナリはリフレクションによってクラス名で動的に作成されます。辞書に関数を動的に作成する方法がない限り – ShitakeOishii

+0

私の解決策は、辞書が作成されたときにすべての 'MessageBase'派生型が可視であると仮定します。場合によっては、そのアセンブリがそのような型を定義するすべてのアセンブリを参照するため、そのアセンブリが必要な型をすべて知っている場合は、辞書を満たすコードを主アセンブリに移動することが可能な場合があります。それ以外の場合は、リフレクションまたは依存性注入コンテナが必要です。 – Phil1970

関連する問題