3

この質問は、次の質問に関連しています: 与えられた System.Type T, Deserialize List<T>

すべての要素のリストを取得するこの関数を考えると...

 public static List<T> GetAllItems<T>()
 {
    XmlSerializer deSerializer = new XmlSerializer(typeof(List<T>));
    TextReader tr = new StreamReader(GetPathBasedOnType(typeof(T)));
    List<T> items = (List<T>)deSerializer.Deserialize(tr);
    tr.Close();
 }

...必要な UID (一意の ID) を持つアイテムを 1 つだけ取得する関数を作成したい:

public static System.Object GetItemByID(System.Type T, int UID)
{

    IList mainList = GetAllItems<typeof(T)>();
    System.Object item = null;

    if (T == typeof(Article))
        item = ((List<Article>)mainList).Find(
            delegate(Article vr) { return vr.UID == UID; });
    else if (T == typeof(User))
        item = ((List<User>)mainList).Find(
            delegate(User ur) { return ur.UID == UID; });

    return item;
}

ただし、GetAllItems<typeof(T)>();呼び出しが適切に形成されていないため、これは機能しません。

質問 1a : GetItemByID() を呼び出すすべてのクラスが要素として UID を持っている場合、一意の要素を適切に返すように 2 番目の関数を修正するにはどうすればよいですか? public static <T> GetItemByID<T>(int UID)できればやってみたい です。

質問 1b : 同じ質問ですが、GetItemByID の関数プロトタイプを変更できないとしますか?

4

7 に答える 7

3

1a. IUniqueIdentityすべての Tがプロパティを定義するインターフェイスを実装していることを確認してUIDから、ジェネリック メソッドが型のみを受け入れるように制約しIUniqueIdentityます。そう:

public static T GetItemById<T>(int UID) where T:IUniqueIdentity
{
    IList<T> mainList = GetAllItems<T>();

    //assuming there is 1 or 0 occurrences, otherwise FirstOrDefault
    return mainList.SingleOrDefault(item=>item.UID==UID); 

}

public interface IUniqueIdentity
{
    int UID{get;}
}
于 2010-11-08T21:45:30.630 に答える
1

GetItemByID()を呼び出すすべてのクラスが要素としてUIDを持っている場合、2番目の関数を修正して一意の要素を適切に返すにはどうすればよいですか?

GetItemByIDメソッドをそれ自体が汎用になるように変更します。public static T GetItemByID<T>(int UID)

同じ質問ですが、GetItemByIDの関数プロトタイプを変更できないとします。

GetAllItems<typeof(T)>()ジェネリックメソッドを呼び出すにはコンパイル時にT型の知識が必要なため、お気づきのとおり、は機能しません。代わりに、を使用して、特定のTMethodInfo.MakeGenericMethod()のメソッドへの閉じた形式の参照を作成します。Type

public static System.Object GetItemByID(System.Type type, int UID) 
{
    Type ex = typeof(YourClass);
    MethodInfo mi = ex.GetMethod("GetItemByID");

    MethodInfo miConstructed = mi.MakeGenericMethod(type);

    // Invoke the method.
    object[] args = new[] {UID};
    return miConstructed.Invoke(null, args);
}
于 2010-11-08T21:44:10.317 に答える
0

1Aに応じて、通常の解決策はUIDプロパティをに抽出することです。

interface IHasUID { public int UID { get; } }

、、ArticleおよびUserその他の実装。次に制約を追加します

public static T GetItemByID<T>(int UID) where T : IHasUID

タイプ、、などを制御ArticleできUserず、これらにこのインターフェイスを実装させることができない場合は、基本的に* *であり、タイプセーフな方法でこれを行うことはできません。

于 2010-11-08T21:42:19.523 に答える
0

コストを気にしない場合は、Reflection に次のようなものがあります。

public static System.Object GetItemByID(System.Type T, int UID)
{

    IList mainList = GetAllItems().OfType<typeof(T)>();

    return mainList.Find(i => (int)(i.GetType().GetFields().Where(f => f.Name == "UID").FirstOrDefault().GetValue(i)) == UID);

}

基本的に、リフレクションを使用して というフィールドの値を取得しますUID

Articleまたはを変更する能力がない場合にのみ、これを使用してください。Userこれらは、1 つのインターフェースから継承してUID、反映することなくフィールドへのアクセスを許可する必要があるためです。

于 2010-11-08T21:56:05.627 に答える
0

そのままシステムに適合するかどうかはわかりませんが、一般的なリストの代わりに KeyedCollection を実装することを考えたことはありますか?

http://msdn.microsoft.com/en-us/library/ms132438%28VS.95%29.aspx

または、基本クラスのコードからカスタム ソリューションへの洞察が得られる場合もあります。

于 2010-11-08T22:43:12.680 に答える
-1

System.Type は既に型です。typeof を実行する必要はありません。

if (T == typeof(Article)) item = ((List)mainList).Find(vr => vr.UID == UID);

于 2010-11-08T21:45:58.307 に答える