1

我有一個C#Windows Phone 8應用程序,對於擁有它的手機,將Compass傳感器用於特定功能。我想修改該類,以便它可以在沒有指南針傳感器的手機上工作。如果(_compass!= null)語句,我不想​​將每個調用都打包到中的Compass對象。我以爲我可以創建一個虛擬的指南針類與存根指南針的方法和屬性,並創建它的實例,而不是指南針,如果手機沒有指南針,但我遇到了問題與抽象Compass類的基類名爲SensorBase。無論我做什麼,我得到的編譯時錯誤:無法創建虛擬C#傳感器類而沒有得到任何構造函數定義的錯誤?

Error 1 The type 'Microsoft.Devices.Sensors.SensorBase<TSensorReading>' has no constructors defined 

指南針類我試圖仿效從SensorBase的可以繼承沒有得到這個錯誤。我從Sensors元數據文件中獲取了Compass類的確切聲明行,並在將類名更改爲CompassDummy後將其插入我的虛擬類中,但仍然出現錯誤。

我的猜測是Compass類可以從SensorBase繼承,而我的dummy類不能,因爲它與SensorBase在同一個Assembly中。也許SensorBase的構造函數標記爲內部或者還有其他類似的「朋友」類似的關係。

我的問題是,有什麼我可以做的,在這種情況下從SensorBase繼承沒有得到這個錯誤?如果沒有,是否還有另一種涉及依賴注入(IOC)的解決方案,當手機沒有指南針時,這有助於實現實例化虛擬類的目標?

這裏是我所得到錯誤的CompassDummy類代碼:

public sealed class CompassDummy : SensorBase<CompassReading> 
{ 
    public CompassDummy() 
    { 

    } 
} // public class CompassDummy 
+0

做,如果你從你的CompassDummy類中刪除構造函數,你得到同樣的錯誤? –

回答

4

My guess is that the Compass class can inherit from SensorBase while my dummy class can't because it is in the same Assembly as SensorBase. Perhaps the constructor for SensorBase is marked internal

正確的。你不應該自己從SensorBase<T>派生出來:它只是Accelerometer,Compass,GyroscopeMotion的基類。

您是否打算在您自己的代碼中使用這個虛擬Sensor類,而不是將它傳遞給任何地方?如果是這樣,這裏使用組成,而不是繼承:

public interface ICompass 
{ 
    void Start(); 
    // Whatever other methods you need 
} 

public class RealCompass : ICompass 
{ 
    private readonly Compass compass; 

    public RealCompass(Compass compass) 
    { 
     this.compass = compass; 
    } 

    public void Start()  
    { 
     this.compass.Start(); 
    } 
} 


public class StubCompass : ICompass 
{ 
    public void Start() 
    { 
     // Do nothing... 
    } 
} 

然後,在你的代碼,使用您的ICompass接口。

+0

正確,但是我必須爲Compass對象公開的所有內容創建一個包裝方法,因爲Compass對象沒有聲明我的ICompass接口。真的很遺憾,幫助設計C#的Anders Heljsberg沒有將Delphi實現代理功能添加到C#中。有時間寫一些管道代碼。 –

+1

@RobertOschler確實如此。但實際上,「Compass」是一個非常小的類,它只會花你幾分鐘的時間來編寫包裝器。 C#7的語言設計討論仍然是開放的:如果你有一個功能建議,現在是時候做出來了!查看Roslyn GitHub回購。 – canton7

+0

包裝完成。絕對期待C#7和Roslyn。 –

1

使用一個接口來允許用canton7替換混凝土羅盤類型as suggested,這是一個很好的解決方案。根據您的需要,另一個需要考慮的解決方案是proxy pattern

基本上,您會創建一個CompassProxy類,您將在整個代碼中使用該類。這個類將具有與框架類似的或相同的方法/屬性,並且它的每個實例將包含對應的實例CompassCompassDummy,這取決於電話的硬件。

調用代理類將被轉發到包含的「後端」指南針類,這將做真正的工作,任何結果將被傳回給調用者。

只是作爲一個例子,這裏是一個CompassProxy類的一些原型代碼:

class CompassProxy { 

    private readonly Compass _realCompass = null; 
    private readonly CompassDummy _dummyCompass = null; 

    private readonly bool _hasCompass = false; 


    public CompassProxy() { 

     // the creation logic could be moved out of this class, if need be 
     if (HasRealCompassHardware()) { 

      _realCompass = Compass.GetDefault(); // ...or whatever is the proper way to obtain an instance 
      _hasCompass = true; 

     } else { 

      _dummyCompass = new CompassDummy(); 

     } 

    } 


    public CompassReading GetCurrentReading() { 

     return _hasCompass ? _realCompass.GetCurrentReading() : _dummyCompass.GetCurrentReading(); 

    } 

} 
+0

查看我對下面canton7的評論。這就是我最終會做的。儘管如此,它仍然與「if(_instance! - null)」技術基本相同。 –

+1

@RobertOschler是的,它歸結爲實踐中的相同工作,只是你想如何分析邏輯的問題。我同意,如果C#提供了編寫傳遞代碼的繁瑣工作的優雅替代品,那將會很不錯。 –

相關問題