2016-09-23 37 views
1

我是新來的泛型,只是想知道是否有可能避免使用更好的面向對象方法在下面的代碼中投射。通過使用泛型避免在下面的代碼中鑄造

public class CollectorFactory 
{ 
    public static MyCollector Create(ICredential credential) 
    { 
     return new MyCollector(credential); 
    } 
} 

public class MyCollector { 

    public MyCredential Credential { get; set; } 

    public MyCollector(ICredential credential) 
    { 
     this.Credential = (MyCredential)credential; 
    } 

    public void Show() 
    { 
     Console.WriteLine(this.Credential.Username); 
     Console.WriteLine(this.Credential.AuthToken); 
    } 
} 

public class MyCredential : ICredential 
{ 
    public string Username{ get; set; } 

    public string AuthToken { get; set; } 
} 

public interface ICredential 
{ 

} 

有沒有辦法救ICredential到MyCredential在MyCollector的構造鑄造?我沒有選擇將Username和AuthToken放入ICredential,因爲它由兩個不同的憑證實現,這兩個憑證都具有不同的屬性集。 CollectorFactory將來將返回不同的MyCollector實例,並且都需要具有不同的憑據。

任何幫助將非常感激。

+0

我假設你在工廠檢查憑證的類型。然後在那裏進行投射,並讓收藏者的構造函數採取特定的類型。除此之外,演員陣容沒有辦法。 –

+2

什麼是泛型?鑄造並不昂貴,爲什麼要避免這種情況?如果您不想投射,則只需將'Credential'聲明爲'public ICredential Credential {get;組; }'。但我認爲將所有內容都保存爲界面並不是一個好主意。你真的需要重新考慮設計/你需要做什麼(而不是你想做什麼)。另外,良好的面向對象方法不會鼓勵你有空的界面。 – kurakura88

回答

1

我不認爲這是可能的,因爲你正在實施不同的憑據,並試圖將它們用於ICredential。

+0

這是不正確的。使用泛型實現此目的的想法是正確的,特別是考慮到OP需要擴展他的解決方案以支持多種auth類型。 –

+0

是的,這是正確的做法,但無法擴展以實現其預期目的。 編輯:你的回答很有道理,很有效率。它應該適合你,nafr1。 – brld

-1

泛型不是這種情況下的解決方案。這裏的問題是您的工廠正在返回特定類型(MyCollector)。解決方案如下:

public class CollectorFactory 
{ 
    public static ICollector Create(MyCredential credential) 
    { 
     return new MyCollector(credential); 
    } 
    public static ICollector Create(OtherCredential credential) 
    { 
     return new OtherCollector(credential); 
    } 
} 

public interface ICollector 
{ 
    void Show(); 
} 

public class MyCollector : ICollector 
{ 

    public MyCredential Credential { get; set; } 

    public MyCollector(MyCredential credential) 
    { 
     this.Credential = credential; 
    } 

    public void Show() 
    { 
     Console.WriteLine(this.Credential.Username); 
     Console.WriteLine(this.Credential.AuthToken); 
    } 
} 

public class MyCredential : ICredential 
{ 
    public string Username{ get; set; } 

    public string AuthToken { get; set; } 
} 

public interface ICredential 
{ 

} 

以上幾乎是工廠設計模式的規範示例。

相反,你也別在工廠類型檢查重載:

public class CollectorFactory 
{ 
    public static ICollector Create(ICredential credential) 
    { 
     if(credential.GetType() == typeof(MyCredential)) 
      return new MyCollector((MyCredential) credential); 
     if(credential.GetType() == typeof(OtherCredential)) 
      return new OtherCollector((OtherCredential) credential); 
    } 
} 
+0

這是一個可怕的模式。由於工廠中的類型引用,將導致引入新的Auth類型變得更加困難。 –

0

這裏是這樣使用泛型的方式。請閱讀我在代碼中的評論。

public class CollectorFactory<T> 
{ 
    public T Create(ICredential credential) 
    { 
     return (T)Activator.CreateInstance(typeof(T), credential); 
    } 
} 

public class MyCollector : BaseCollector 
{ 
    public dynamic Credential { get; private set; } 

    public MyCollector(ICredential credential) 
     : base(credential) 
    { 
     this.Credential = credential; 
    } 

    // Having this method here limits your ability to make it more generic. 
    // Consider moving this to MyCredential since it refers to specific properties in MyCredential. 
    // If that is not what you want, then you must do a type check before calling methods/ accessing props in Credentials. 
    public void Show() 
    { 
     Console.WriteLine(this.Credential.Username); 
     Console.WriteLine(this.Credential.AuthToken); 
    } 
} 

public class MyCredential : ICredential 
{ 
    public string Username { get; set; } 

    public string AuthToken { get; set; } 
} 

public abstract class BaseCollector : ICredentialCollector 
{ 
    protected BaseCollector(ICredential credential) 
    { 
     if (credential == null) 
     { 
      throw new ArgumentNullException(nameof(credential)); 
     } 
    } 
} 

public interface ICredentialCollector 
{ 
} 

public interface ICredential 
{ 
} 

// test implementation 
public class TestClass 
{ 
    public void AuthFactoryTest() 
    { 
     // test auth instance 
     MyCredential auth = new MyCredential() {AuthToken = "asfgasdgdfg", Username = "xuser"}; 

     // Create test factory 
     var fact = new CollectorFactory<MyCollector>(); 
     var myCollector = fact.Create(auth); 

     // Do what you need to do to collector object 
     myCollector.Show(); 
    } 
} 
+1

這裏的關鍵點不是泛型,而是動態的使用 – Kenneth

+0

這是否重要?真正關鍵的一點是靈活性或適應未來需求的能力。 –