2013-10-24 35 views
3

是否有可能有選擇地選擇(使用裝飾器可能?)根據調用的構造函數將對象暴露給哪些方法?有選擇地暴露基於構造函數的方法嗎?

例如我的類有2個構造函數,一個是空的,另一個傳入文件路徑字符串。

public class MyClass 
{ 
    private readonly string _filePath; 
    public MyClass() 
    { 

    } 

    public MyClass(string filePath) 
    { 
     _filePath = filePath 
    } 

    public Export() 
    { 
     var fi = new FileInfo(_filePath); 
    } 
} 

是否有可能,當我創建一個新的MyClass的對象,只有當我使用構造函數參數暴露導出方法?

var myClass = new MyClass(); 
//myClass.Export() not available 

var myClass = new MyClass(@"C:\"); 
//myClass.Export() is available 

回答

1

這是一個標誌,你應該有兩種不同的類型。也許他們都應該是父類型的子類型(可能是抽象的),或者應該簡單地擴展其他類型。

然後,您可以根據您是否有字符串構造適當類型的實例。帶有字符串的類型可以有其他方法。

public class MyClass 
{ 
    public MyClass() 
    { 

    } 

    public void Foo() 
    { 
     //todo do stuff 
    } 
} 

public class BetterMyClass : MyClass 
{ 
    private readonly string _filePath; 

    public BetterMyClass(string filePath) 
    { 
     _filePath = filePath; 
    } 

    public void Export() 
    { 
     var fi = new FileInfo(_filePath); 
    } 
} 

然後您的使用非常有效:

var myClass = new MyClass(); 
//myClass.Export(); //syntax error 

var myClass2 = new BetterMyClass(@"C:\"); 
myClass.Export(); //works 
+0

你仍然有知道哪些鍵入要使用的問題做。換句話說,這是一個編譯時問題。 –

+0

@RobertHarvey在上下文中顯示他不需要將變量聲明爲父類型;它可以是更多的派生類型,所以我沒有看到問題。 – Servy

+0

正如我所看到的那樣,問題是如果你已經知道對象的類型,那麼所有這些都是沒有意義的,如果你不知道類型,那麼你不能說它是任何特定的派生類型。 –

0

這是可能的,只是不是你在這裏顯示的方式。你會想創建一個只有默認構造函數並且沒有Export方法的新類。然後創建第二個繼承自第一個類的類,並且構造函數需要string,並且還會公開Export方法。

public class MyClass 
{ 
    public MyClass() 
    { } 
} 

public class MyOtherClass : MyClass 
{ 
    private readonly string value; 

    public MyOtherClass(string value) 
    { 
     this.value = value; 
    } 

    public string Export() { return this.value; } 
} 

如果你絕對必須有選擇性,這在我看來是一個愚蠢的設計決策,那麼你會想要去與在運行時使用的代碼生成,要麼或不執行內置型方法。

0

據我所知,沒有,這不能在你的意思的方式來完成。如果可以的話,編譯器通常無法知道所討論的方法是否對所討論的對象有效。然後它將不得不在運行時檢查。如果在不可用時調用該方法,則會收到運行時異常。您可以基於構造函數中設置的標誌自行拋出異常。

然而,最終,你真正想要的是一個有附加選項的子類。這將是一種更安全的方式來啓用這種類型的功能。

1

不是直接。你可以:

  1. 創建返回IMyInterface類型的對象工廠方法,然後嘗試轉換爲包含要公開方法的類型。如果對象不是暴露該方法的類型,則投射將失敗。或..

  2. 使用dynamic對象。如果方法不存在,方法調用將在運行時失敗。

0

你可以這樣使用工廠模式,並返回一個不同的接口

public interface IExportInterface 
{ 
    void Export(); 
} 

public interface INoExportInterface 
{ 
    //Other methods 
} 

internal class MyClass : IExportInterface, INoExportInterface 
{ 
    private readonly string _filePath; 

    public MyClass() 
    { 
    } 

    public MyClass(string filePath) 
    { 
     _filePath = filePath; 
    } 

    public void Export() 
    { 
     var fi = new FileInfo(_filePath); 
    } 
} 

public class MyClassFactory 
{ 
    public static IExportInterface GetMyClass(string filePath) 
    { 
     return new MyClass(filePath); 
    } 

    public static INoExportInterface GetMyClass() 
    { 
     return new MyClass(); 
    } 
} 
+0

這樣做的問題是,您要麼必須在兩個接口中公開所有MyClass方法,要麼將返回對象強制轉換回MyClass以訪問MyClass方法,這會破壞目的(因爲它暴露了這兩個接口)。 –