2011-12-15 60 views
1

是否可以定義如何將內置對象轉換爲C#中的接口?接口不能定義運算符。我有一個非常簡單的界面,允許索引訪問,而不是突變:C#轉換爲接口

public interface ILookup<K, V> 
{ 
    V this[K key] { get; } 
} 

我希望能夠投出Dictionary<K, V>ILookup<K, V>。在我理想中的夢幻世界,這將是這樣的:

//INVALID C# 
public interface ILookup<K, V> 
{ 
    static implicit operator ILookup<K, V>(Dictionary<K, V> dict) 
    { 
     //Mystery voodoo like code. Basically asserting "this is how dict 
     //implements ILookup 
    } 
    V this[K key] { get; } 
} 

我已經工作了作爲一個解決方法是這樣的:

public class LookupWrapper<K, V> : ILookup<K, V> 
{ 
    private LookupWrapper() { } 

    public static implicit operator LookupWrapper<K, V>(Dictionary<K, V> dict) 
    { 
     return new LookupWrapper<K, V> { dict = dict }; 
    } 

    private IDictionary<K, V> dict; 
    public V this[K key] { get { return dict[key]; } } 
} 

這工作,並意味着我現在可以直接從字典轉換爲ILookup,但男孩是否覺得錯綜複雜...

有沒有更好的方法來強制轉換到接口?

+0

實現在你的環境是不是適合使用抽象類,而不是接口? – 2011-12-15 01:13:39

回答

0

感謝@MBabcock的評論,我意識到我正在考慮這個錯誤。我提拔的界面到全階級如下:

public class Lookup<K, V> 
{ 
    private readonly Func<K, V> lookup; 
    protected Lookup(Func<K, V> lookup) 
    { 
     this.lookup = lookup; 
    } 

    public static implicit operator Lookup<K, V>(Dictionary<K, V> dict) 
    { 
     return new Lookup<K, V>(k => dict[k]); 
    } 

    public V this[K key] 
    { 
     get { return lookup(key); } 
    } 
} 

任何進一步的轉換,我需要這樣我可以簡單地添加一個隱含的操作

2

由於接口不能包含實際代碼,因此需要一些類來承載演員代碼。這可以是一個實現接口的類(顯然),否則它需要成爲一個包裝類,就像你擁有的包裝類一樣。沒有第三種選擇。

¹您「調用」演員的方式可能不同(例如,您可以在擴展方法後面隱藏LookupWrapper的構造),但這不會改變事情。

0

如果您對字典有任何控制權,您可以對它進行子類化並在您的子類中覆蓋this[]。然後使用你的新字典,而不是.NET。

0

你能做的最好是使用擴展方法和包裝類...

public interface ILookup<K, V> 
{ 
    V this[K key] { get; } 
} 

public class DictWrapper<K, V> : ILookup<K, V> 
{ 
    Dictionary<K, V> dictionary; 

    public DictWrapper(Dictionary<K, V> dictionary) 
    { 
     this.dictionary = dictionary; 
    } 

    public V this[K key] 
    { 
     get { return dictionary[key]; } 
    } 

    protected internal Dictionary<K, V> InnerDictionary { get { return dictionary; } } 
} 

public static class Extensions 
{ 
    public static ILookup<K, V> ToLookup<K, V>(this Dictionary<K, V> dictionary) 
    { 
     return new DictWrapper<K, V>(dictionary); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Dictionary<string, int> data = new Dictionary<string, int>(); 

     data.Add("Office", 100); 
     data.Add("Walls", 101); 
     data.Add("Stair", 30); 

     ILookup<string, int> look = data.ToLookup(); 
    } 
} 
0

這是一種相當詭異的語言混雜,但有一種方法。我假設你基本上試圖將一個接口應用到已經有你想要的特徵的類上,你只需要一個子集(就像你的例子)。

您可以使用TransparentProxy/RealProxy對在運行時創建實現任何接口(或MarshalByRef對象)的類。你需要實現一個抽象方法來處理這個調用,但是用一點點肘部油脂就可以使這種通用性足以應付這種情況。

我們遇到了一個類似的問題,它包裝非常糟糕的庫(我們不得不使用反射來調用每個方法)。因此,我們不是寫出大量的自定義反射代碼,而是編寫了通用的案例,然後編寫了一些匹配簽名的接口。然後我們直接使用這些接口。我們甚至自動打包/解包對象,這樣我們就可以讓我們的接口方法返回其他接口,並且它們都可以正常工作。

有一個超長的方法的書面記錄,並在http://blog.paulhounshell.com/?s=Duck