2010-09-30 56 views
1

貝塞爾we can't use generic type attributes,有沒有替代解決方案?也許一個例子是有幫助的討論:泛型類型屬性的任何替代解決方案?

public abstract class ErrorHandler { } 
public class AccessHandler : ErrorHandler { } 
public class ConnectionHandler : ErrorHandler { } 
public class OtherHandler : ErrorHandler { } 

public class CoHandler<T> : Attribute where T : ErrorHandler 
{ 
    public T GetHandler() 
    { 
     return default(T); // just an example 
    } 

} 
public enum Errors 
{ 
    [CoHandler<AccessHandler>()] 
    Access, 
    [CoHandler<ConnectionHandler>()] 
    Connection, 
    [CoHandler<OtherHandler>()] 
    Other 
} 

回答

0

在你的榜樣,通過改變枚舉成一個類,使用接口,而不是屬性,可以實現相同的功能。

您可以使用作爲測試接口實現,也可以爲接口編寫擴展方法。

您也可以在Errors類上實現方法,給出比普通的舊枚舉更多的範圍。

{ 
    Errors error = Errors.Access; 
    var handler = error.GetHandler(); 
} 

public abstract class ErrorHandler { } 
public class AccessHandler : ErrorHandler { } 
public class ConnectionHandler : ErrorHandler { } 
public class OtherHandler : ErrorHandler { } 

public interface CoHandler<T> 
    where T : ErrorHandler 
{ 
    T GetHandler(); 
} 

public abstract class Errors 
{ 
    public static Errors Access = new AccessError(); 
    public static Errors Connection = new ConnectionError(); 

    public abstract ErrorHandler GetHandler(); 

    private class AccessError : Errors, CoHandler<AccessHandler> 
    { 
     public override ErrorHandler GetHandler() 
     { 
      return new AccessHandler(); 
     } 

     AccessHandler CoHandler<AccessHandler>.GetHandler() 
     { 
      return new AccessHandler(); 
     } 
    } 

    private class ConnectionError : Errors, CoHandler<ConnectionHandler> 
    { 
     public override ErrorHandler GetHandler() 
     { 
      return new ConnectionHandler(); 
     } 

     ConnectionHandler CoHandler<ConnectionHandler>.GetHandler() 
     { 
      return new ConnectionHandler(); 
     } 
    } 

} 
+0

這是最好的方式,與上面的其他答案進行比較。 – 2010-10-03 04:38:03

4

那麼,你可以在屬性構造函數中接受類型或類型的名稱參數。例如

[CoHandler(typeof(AccessHandler))] 

[CoHandler("[Fully or partially qualified type name]")] 

前更容易使用,而後者是有用的,當你不希望採取或不能採取在包含類型的程序集的依賴。

順便說一句,return default(T);將始終返回null,我希望它只是爲了說明的目的。這裏的例子,你如何使用類型參數:

public class CoHandler : Attribute 
{ 
    private Type _Type; 

    public CoHandler(Type type) 
    { 
     _Type = type; 

     // Use reflection to validate type argument to see if it has 
     // inherited from ErrorHandler and check if its has parameterless 
     // constructor 
    } 

    public ErrorHandler GetHandler() 
    { 
     return (ErrorHandler)Activator.CreateInstance(_Type); 
    } 

} 
+0

但是我會失去'Where T:ErrorHandler'檢查,對嗎?有沒有想法保持這個編譯時檢查? – 2010-09-30 04:26:28

+1

@丹尼 - 是的,這是正確的。你不能讓編譯器做這個檢查。您可能會使用FxCop等靜態分析工具進行編譯/編譯時檢查,然後編寫自定義規則但是IMO,這太麻煩了,而且您很可能在第一輪自檢中捕獲不正確的類型用法。 – VinayC 2010-09-30 04:31:41