2016-12-22 10 views
0

同様の属性を持つ2つの無関係なオブジェクトのハッシュセットを取る関数を一般化する方法があるかどうかを調べようとしています。私は以下のいくつかのサンプルコードがあります。関数の一般化

private IList<IDictionary<string, string>> BuildDictionary(HashSet<ClassA> ClassA) 
{ 
    IList<IDictionary<string, string>> data = new List<IDictionary<string, string>>(); 
    foreach (var a in ClassA) 
    { 
     Dictionary<string, string> aDictionary = new Dictionary<string, string>(); 
     aDictionary.Add(a.Code, a.Code + "," + a.Name); 
     data.Add(aDictionary); 
    } 

    return data; 
} 

private IList<IDictionary<string, string>> BuildDictionary(HashSet<ClassB> ClassB) 
{ 
    IList<IDictionary<string, string>> data = new List<IDictionary<string, string>>(); 
    foreach (var b in ClassB) 
    { 
     Dictionary<string, string> bDictionary = new Dictionary<string, string>(); 
     bDictionary.Add(b.Code, b.Code + "," + b.Name); 
     data.Add(bDictionary); 
    } 

    return data; 
} 

このように明らかなように、コードから、二つのクラスが関連していないのが、彼らの両方がHashSetのであり、同様の属性(コードネーム)を含有します。私はジェネリックTを使用しようとしましたが、ジェネリッククラスTを作成していないために失敗しました。新しいクラスを作成せずにこの問題を回避する方法はありますか?

+3

両方のクラスのインターフェイスはどうですか? – Pikoh

+0

インターフェイスを実装できるように両方のクラスにアクセスできますか? – pstrjds

+0

あなたは、クラスが "typeof"か "is"であるかどうかを確認するためにリフレクションを使用し、T:class " – Luther

答えて

3

ソースクラスが封印されているか、共通のインターフェイスに変更できない場合は、ほとんどのLINQクエリのように、必要な部分にアクセサを使用できます。

ここに実装例があります。 toKey()toMemberValue()はより適切に名前を付けることができますが、関連するプロパティを取得するためにラムダを指定することができ、必ず同じプロパティ名を持つクラスに依存しないクラスに対して、それに応じてラムダが書かれている限り。 Main()は、この方法を両方のケースで使用するとどのように見えるかを示しています。

public IList<IDictionary<string, string>> BuildDictionary<T>(HashSet<T> sourceSet, Func<T, string> toKey, Func<T, string> toMemberValue) 
{ 
    IList<IDictionary<string, string>> data = new List<IDictionary<string, string>>(); 

    foreach (var element in sourceSet) 
    { 
    Dictionary<string, string> newLookup = new Dictionary<string, string>(); 
    newLookup.Add(toKey(element), $"{toKey(element)},{toMemberValue(element)}"); 
    data.Add(newLookup); 
    } 

    return data; 
} 

void Main() 
{ 
    HashSet<ClassA> setOfAs = new HashSet<ClassA>(new[] { new ClassA { Code = "foo", Name = "bar" }, new ClassA { Code = "foo2", Name = "bar2" } }); 
    HashSet<ClassB> setOfBs = new HashSet<ClassB>(new[] { new ClassB { Code = "foo", Name = "bar" }, new ClassB { Code = "foo2", Name = "bar2" } }); 

    var lookupOfAs = BuildDictionary(setOfAs, x => x.Code, x => x.Name); 
    var lookupOfBs = BuildDictionary(setOfBs, x => x.Code, x => x.Name); 
} 

// Define other methods and classes here 
public class ClassA 
{ 
    public string Code { get; set; } 
    public string Name { get; set; } 
} 

public class ClassB 
{ 
    public string Code { get; set; } 
    public string Name { get; set; } 
} 
4

両方のタイプのソースコードを所有している場合は、共通のインターフェイスを実装できます。

private IList<IDictionary<string, string>> BuildDictionary<T>(HashSet<T> someHashSetOfTs) where T : ICommon 
{ 
    IList<IDictionary<string, string>> data = new List<IDictionary<string, string>>(); 
    foreach (var a in someHashSetOfTs) 
    { 
     Dictionary<string, string> aDictionary = new Dictionary<string, string>(); 
     aDictionary.Add(a.Code, a.Code + "," + a.Name); 
     data.Add(aDictionary); 
    } 

    return data; 
} 

インタフェース定義

public interface ICommon { 
    string Code {get; } 
    string Name {get; } 
} 

そして今、両方のタイプClassAClassBICommonを適用します。

関連する問題