2011-03-21 74 views
1

我創建了一個自我搜索程序集,它具有可實現的ISearchable接口。它還提供了搜索電話號碼的功能,因此它具有實現ISearchable的IPhoneNumberSearchable。然後我通過裝配尋找實現IPhoneNumberSearchable的任何內容並調用Search。如果類實現了IPhoneNumberSearchable和ISearchable,它只會調用ISearchable方法。關於如何使這項工作的任何想法?代碼跟隨通用方法,它採用實現另一個接口的接口,而不是調用正確的方法

public class SearchManager 
{ 



    private ISearchItem[] Search<T>(string searchValue) where T: class,ISearchable 
    { 

     Assembly current = System.Reflection.Assembly.GetExecutingAssembly(); 

     IEnumerable<T> instances = from t in Assembly.GetExecutingAssembly().GetTypes() 
         where t.GetInterfaces().Contains(typeof(T)) 
           && t.GetConstructor(Type.EmptyTypes) != null 
         select Activator.CreateInstance(t) as T; 

     var list = new List<ISearchItem>(); 
     foreach (T item in instances) 
     { 
      try 
      { 
       T i = item as T; 
       list.AddRange(item.Search(searchValue)); 
      } 
      catch (System.Exception) { } 
     } 


     return list.ToArray(); 

    } 


    /// <summary> 
    /// Searches the specified search value. 
    /// </summary> 
    /// <param name="searchValue">The search value.</param> 
    /// <returns></returns> 
    public ISearchItem[] Search(string searchValue) 
    { 
     return Search<ISearchable>(searchValue); 
    } 


    /// <summary> 
    /// Searches for phone number. 
    /// </summary> 
    /// <param name="phoneNumber">The phone number.</param> 
    /// <returns></returns> 
    public ISearchItem[] SearchForPhoneNumber(string phoneNumber) 
    { 
     return Search<IPhoneSearchable>(phoneNumber); 
    } 

} 


/// <summary> 
/// 
/// </summary> 
public interface ISearchable 
{ 

    ISearchItem[] Search(string searchValue); 
} 

/// <summary> 
/// 
/// </summary> 
public interface ISearchable 
{ 

    ISearchItem[] Search(string searchValue); 
} 



public class CustomerManager : Search.IPhoneSearchable,Search.ISearchable 
{ 


    /// <summary> 
    /// Searches the specified phone number. 
    /// </summary> 
    /// <param name="phoneNumber">The phone number.</param> 
    /// <returns></returns> 
    Search.ISearchItem[] Search.IPhoneSearchable.Search(string phoneNumber) 
    { 
     //Search based upon phone number    
    } 

    /// <summary> 
    /// Searches the specified search value. 
    /// </summary> 
    /// <param name="searchValue">The search value.</param> 
    /// <returns></returns> 
    Search.ISearchItem[] Search.ISearchable.Search(string searchValue) 
    { 
     //Search on anything code 
    } 
} 
+0

我沒有解決您的問題,但看看MEF - 它看起來像要重新發明輪子:http://mef.codeplex.com/ – BrokenGlass 2011-03-21 16:20:01

回答

1

此代碼不按預期工作,因爲它工作正是根據語言規範。

基本上在你類CustomManager中你可以隱式地和明確地實現ISearchable。如果你想嘗試調用此方法在常規碼(不使用反射),它看起來像

CustomManager k = new CustomManager(); 
IPhoneSearchable x = k; 
x.Search("strings"); //calls IPhoneSearchable.Search() 
ISearchable y = k; 
y.Search("string"); //calls ISearchable.Search() 
k.Search("string); //calls ISearchable.Search()!!! 

的原因恰恰不是混淆編碼器。您在類中實現接口,以便每次調用此方法都應調用此實現。如果由於某種其他原因您明確實現了另一個接口您需要指定您希望發生這種精確調用。

我不想介入你的設計,但對我來說這看起來有點奇怪。一種方法搜索某些東西,另一種搜索特定的東西,但兩者具有相同的簽名,同時提供稍微不同的功能。也許應該改變了IPhoneSearchable提供了一個名爲

SearchPhones(string[] filters) 

方法實際調用從而隱藏從用戶實現細節的方法搜索。通過提供Inteface IPhoneSearchable,您在合同規範中除了提供標記界面外什麼也不做。

所以解決您的代碼你或許應該創建實際MethodCalls的集合(因此CustomManager有兩種方法調用,從ISearchable搜索和搜索IPhoneSearchable)

和迭代這個集合,並調用每個方法。

問候 盧克

+0

其實'K。搜索(「東西」)不存在:) – 2011-03-21 17:00:09

+0

對不起,AS CII的確我認爲有隱式的方法實現。確實沒有k.Search(「Something」) – luckyluke 2011-03-21 20:04:24

0

對於由幸運的路克你的代碼解釋的原因將無法正常工作。但是,而不是創建

實際MethodCalls(因此CustomManager有兩種方法調用,從ISearchable搜索和IPhoneSearchable搜索),然後遍歷這個集合,並調用每個方法

你可以集合做這樣的事情(我已經略有改變您的代碼):

public interface ISearch 
{ 
    IEnumerable<string> Search(string filter); 
} 

public interface IPhoneSearch : ISearch 
{ 
    new IEnumerable<string> Search(string filter); 
} 

public class Searchable : IPhoneSearch 
{ 
    public IEnumerable<string> Search(string filter) 
    { 
     yield return "Phone!"; 
    } 

    IEnumerable<string> ISearch.Search(string filter) 
    { 
     yield return "Normal!"; 
    } 
} 

然後在你的搜索:

static IEnumerable<string> Search<T>(string searchValue) where T : class, ISearch 
{ 
    var current = Assembly.GetExecutingAssembly(); 
    var instances = from t in Assembly.GetExecutingAssembly().GetTypes() 
        where !t.IsInterface 
        where typeof(T).IsAssignableFrom(t) 
        select (dynamic)Activator.CreateInstance(t); 

    foreach (var item in instances) 
    { 
     foreach (var occurrence in item.Search(searchValue)) 
     { 
      yield return occurrence; 
     } 
    } 
} 

無論如何,我會建議改變這個實現,就像luckyluke說的那樣。

+0

你的觀點是有效的ASCII,我們不知道的是,如果他只想打電話搜索或搜索或兩者(因此我建議的方法呼叫收集)。並且+1使用IsAssignalbleFrom(這樣一個清晰的事情,但略有不同的方法 - 但它可能是他有隱式轉換.. – luckyluke 2011-03-21 20:06:32

+0

是的我想能夠分開打電話給他們我也想定義一個或兩個的能力。我的主要問題是即使泛型類型是IPhoneSearchable,當我調用搜索泛型類型(IPhoneSearchable)時,它仍然稱爲ISearchable方法。 – 2011-03-24 13:58:11

0

我的主要問題是即使泛型類型是IPhoneSearchable,當我調用搜索泛型類型(IPhoneSearchable)時,它仍然稱爲ISearchable方法。

我可以讓它工作的唯一方法是通過反射使用以下代碼來調用搜索。

 var list = new List<ISearchItem>(); 
     foreach (T item in instances) 
     { 


      try 
      { 

       var type = typeof(T); 

       var inter = item.GetType().GetInterface(type.Name); 

       var results = (ISearchItem[])inter.InvokeMember("Search", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public, null, item, new object[] { searchValue }); 
       if(results != null) 
        list.AddRange(results); 
      } 
      catch (System.Exception) { } 
     } 
相關問題