3

私は.netで小さなシリアル化ライブラリを書いています。目標は、XmlSerialize に代わるものを用意することですが、構成が簡単で、モデルを属性で台無しにすることはありません。

私が直面している問題は ICollection<T>、モデルのトラバース中に見つけたそれぞれの型が必要だということです。素朴なアプローチは次のとおりです。

 var theType=myModel.GetType().GetGenericArguments()[0];

ICollection<T>ただし、特定の Tから派生するクラスには役立ちません。

public class MyClass:A,ICollection<B>{}

リフレクションでインターフェースを取得してみました

  var iCollectionInterface =
  o.GetType().GetInterfaces()
     .Where(i => i.IsGenericType)
     .Select(i => i.GetGenericTypeDefinition())
     .FirstOrDefault(i => i == typeof(ICollection<>));

しかし、それはインターフェイスの定義のみを記述し、その使用法を記述していないからではありませんiCollectionInterface.GetGenericArguments()[0]TB

何か案は?私もそれが必要ですIDictionary<TKey, TValue>が、それは基本的に同じ問題であり、同じ解決策があります。

ありがとうございました!

編集

みんなありがとう、これが私が最終的に得たものです:

public static Type GetTypeParameter(object o, Type typeToSearch, int argumentNumber)
{
    return o.GetType()
            .GetInterfaces()
            .Where(i => i.IsGenericType)
            .Where(i => i.GetGenericTypeDefinition() == typeToSearch)
            .Select(t => t.GetGenericArguments()[argumentNumber])
            .FirstOrDefault();
}
4

3 に答える 3

2

これが必要なものです: Type.GetGenericArguments Method

だから、

class MyDictionary: IDictionary<string, decimal>
{
    ...
}

この拡張方法を試してください:

public static Type[] GetClosingArguments<T>(this Type type)
{
    Type iType = typeof(T).GetInterfaces()
                          .FirstOrDefault(i => i.IsGenericType &&
                                     i.GetGenericTypeDefinition() == type);
    if (iType == null)
        return null;
    else
        return iType.GetGenericArguments();
}

このような

Type[] types = typeof(IDictionary<,>).GetClosingArguments<MyDictionary>();
if (types != null)
{
    foreach (Type t in types)
        Console.WriteLine(t.Name);
}

またはその逆:

public static Type[] GetClosingArguments(this Type type, Type baseGenericType)
{
    Type iType = type.GetInterfaces()
                     .FirstOrDefault(i => i.IsGenericType &&
                               i.GetGenericTypeDefinition() == baseGenericType);
    if (iType == null)
        return null;
    else
        return iType.GetGenericArguments();
}

と呼ばれる

Type[] types = typeof(MyDictionary).GetClosingArguments(typeof(IDictionary<,>));
于 2012-12-05T08:29:04.990 に答える
2

コメントから、コレクションをフィルタリングして ICollection のみを含める方法を理解する必要があるようです。次の方法でその目標を達成できます。

var iCollectionInterfaces =
      from i in o.GetType().GetInterfaces()
      where i.IsGenericType 
            && i.GetGenericTypeDefinition() == typeof(IColection<>)
      select i;

その後、コレクションを反復処理し、各型引数で必要なことを何でも行うことができます

//same type might implement ICollection<T> more than once
foreach(var collection in iCollectionInterfaces) {
     //More than one is invalid for ICollection<T>
    var T = collection.GetGenericArguments().Single();
    //do what ever you need
}

もちろん、より一般的なものにしたい場合。つまり、複数の型引数を持つインターフェイス/型をサポートするには、呼び出しを削除しSingleて型引数の反復に置き換える必要があります

于 2012-12-05T09:31:46.877 に答える
0

次の呼び出しが問題だと思います

.Select(i => i.GetGenericTypeDefinition())

ジェネリック引数が定義されたクローズ ジェネリック型を取得すると、そのジェネリック定義が取得されます。これはオープンであり、 のみを認識しTます。呼び出しも変更する必要があるかもしれませんがFirstOrDefault、閉じた型が等しいかどうかはわかりませんICollection<>

于 2012-12-05T08:28:29.917 に答える