2017-07-20 14 views
0

同じインターフェイス異なるCTORのimplementaion

public class Ipu6CalibraitionToolsLoader : ICalibrationToolsLoader 
{ 
     private string _selectedSensorType; 
     public Ipu6CalibraitionToolsLoader(string selectedSensorType) 
     { 
      _selectedSensorType = selectedSensorType; 
      _ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile(_selectedSensorType)); 
      InitCmcOrder(); 
     } 

     public string GetDefaultIspFile(string selectedSensorType = null) 
     { 
      string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 
      string pathSuffix = null; 
      switch ((IPU6SensorType)Enum.Parse(typeof(IPU6SensorType), selectedSensorType)) 
      { 
       case IPU6SensorType.None: 
        break; 
       case IPU6SensorType.Bayer: 
        pathSuffix = "IPUs\\IPU6\\IPU6DefaultsIspFile.xml"; 
        break; 
       case IPU6SensorType.MD: 
        pathSuffix = "IPUs\\IPU6\\IPU6MdDefaultsIspFile.xml"; 
        break;     
       default: 
        throw new ArgumentOutOfRangeException("selectedSensorType", selectedSensorType, null); 
      } 

      if (pathSuffix != null) 
      { 
       string path = Path.Combine(location, pathSuffix); 
       return path; 
      } 
      throw new Exception("missing defaultIspFileXml"); 
     } 

    public void InitCmcOrder() 
    { 
     _cmcCalibrationToolsOrder = new List<CalibrationGroup> 
     { 
      CalibrationGroup.GeneralDataTools, 
      CalibrationGroup.SensorAndModuleSettingsTools, 
      CalibrationGroup.LateralChromaticAberrationTool, 
     }; 
    } 
} 


public class Ipu4CalibraitionToolsLoader : ICalibrationToolsLoader 
{ 
    public Ipu4CalibraitionToolsLoader() 
    { 
     _ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile()); 
     InitCmcOrder(); 
    } 

    public string GetDefaultIspFile(string selectedSensorType = null) 
    { 
     string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 
     string pathSuffix = "IPUs\\Broxton\\IPU4DefaultsIspFile.xml"; 
     string path = Path.Combine(location, pathSuffix); 
     return path; 
    } 

    public void InitCmcOrder() 
    { 
     _cmcCalibrationToolsOrder = new List<CalibrationGroup> 
     { 
      CalibrationGroup.GeneralDataTools, 
      CalibrationGroup.SensorAndModuleSettingsTools, 
      CalibrationGroup.LateralChromaticAberrationTool, 
     }; 
    } 
} 

基本的な機能のほとんどは、しかし、コンストラクタのような関数と同じであり、GetDefaultIspは異なる実装を持っている必要があります。

私は継承を使用しようとしましたが、コンストラクタ内で仮想関数を呼び出すことは大きなNO NOです。 そうする別の方法を提案できますか?

2つのクラスが同じインターフェイスを使用していますが、いくつかのメソッドには異なる実装が必要ですか?

私は、コンストラクタの後に呼び出される必要があるInit()のような別の関数を持つことは望ましくありません。

+1

インタフェース定義は表示できますか? –

+1

インターフェイスと2つのクラスの完全なソースコードを表示してください。 – mjwills

+0

@RomanoZumbéインタフェース – Gilad

答えて

2

EDIT:問題を解決するためのIoC実装の追加!

IoCのバージョン

のIoCソリューションは、私の意見では、道よりエレガントなおそらくもう少し複雑に維持するためにあなたがIoCのに使用されていないときです。

クレジットはplalxに記載されています。

// There is no need for an interface anymore (but you can keep it of course) 
public class IpuCalibrationToolsLoader 
{ 
    private string _selectedSensorType; 
    private string _ispSectionUiSettings; 
    private List<CalibrationGroup> _cmcCalibrationToolsOrder; 

    public IIspFileProvider Provider { get; private set; } 

    // Notice the internal constructor. No one will be able to create an instance of IpuCalibrationToolsLoader out of your assembly except the factory 
    internal IpuCalibrationToolsLoader(IIspFileProvider provider, string selectedSensorType = null) 
    { 
     this.Provider = provider; 
     _selectedSensorType = selectedSensorType; 

     _ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(provider.GetDefaultIspFile(_selectedSensorType)); 

     this.InitCmcOrder(); 
    } 

    public void InitCmcOrder() 
    { 
     _cmcCalibrationToolsOrder = new List<CalibrationGroup> 
     { 
      CalibrationGroup.GeneralDataTools, 
      CalibrationGroup.SensorAndModuleSettingsTools, 
      CalibrationGroup.LateralChromaticAberrationTool, 
     }; 
    } 

    [..] // Since the Provider is exposed as a properties of your IpuCalibrationClassLoader, there is no need for defining the GetDefaultIspFile methods within this class 
} 

public interface IIspFileProvider 
{ 
    string GetDefaultIspFile(string selectedSensorType = null); 
} 

public class Ipu6FileProvider : IIspFileProvider 
{ 
    public string GetDefaultIspFile(string selectedSensorType = null) 
    { 
     string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 
     string pathSuffix = null; 
     switch ((IPU6SensorType)Enum.Parse(typeof(IPU6SensorType), selectedSensorType)) 
     { 
      case IPU6SensorType.None: 
       break; 
      case IPU6SensorType.Bayer: 
       pathSuffix = "IPUs\\IPU6\\IPU6DefaultsIspFile.xml"; 
       break; 
      case IPU6SensorType.MD: 
       pathSuffix = "IPUs\\IPU6\\IPU6MdDefaultsIspFile.xml"; 
       break; 
      default: 
       throw new ArgumentOutOfRangeException("selectedSensorType", selectedSensorType, null); 
     } 

     if (pathSuffix != null) 
     { 
      string path = Path.Combine(location, pathSuffix); 
      return path; 
     } 
     throw new Exception("missing defaultIspFileXml"); 
    } 
} 

public class Ipu4FileProvider : IIspFileProvider 
{ 
    public string GetDefaultIspFile(string selectedSensorType = null) 
    { 
     string location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 
     string pathSuffix = "IPUs\\Broxton\\IPU4DefaultsIspFile.xml"; 
     string path = Path.Combine(location, pathSuffix); 
     return path; 
    } 
} 

public static class IpuCalibrationToolsLoaderFactory 
{ 
    public static IpuCalibrationToolsLoader GetIpu4CalibrationToolsLoader() 
    { 
     return new IpuCalibrationToolsLoader(new Ipu4FileProvider()); 
    } 

    public static IpuCalibrationToolsLoader GetIpu6CalibrationToolsLoader(string selectedSensorType) 
    { 
     return new IpuCalibrationToolsLoader(new Ipu6FileProvider(), selectedSensorType); 
    } 
} 

継承バージョン

はここで抽象クラスを使用したバージョンです。抽象クラスはインスタンス化できないクラスです。それだけでいくつかのコードを保持している:

public abstract class BaseCalibrationToolsLoader : ICalibrationToolsLoader 
{ 
    public BaseCalibrationToolsLoader() 
    { 
     // put here the shared constructor code 
     _cmcCalibrationToolsOrder = new List<CalibrationGroup> 
     { 
      CalibrationGroup.GeneralDataTools, 
      CalibrationGroup.SensorAndModuleSettingsTools, 
      CalibrationGroup.LateralChromaticAberrationTool, 
     }; 
    } 

    public List<CalibrationGroup> GetCmcGroupOrder() 
    { 
     // Put here the shared code among the two implementation 
    } 

    // As the implementation is different, you declare the method abstract so you only implement it in the concret classes 
    public abstract string GetDefaultIspFile(string selectedSensorType = null); 
} 

さて、あなたは抽象クラスから派生した具体的な実装を作成することができます抽象的なコンストラクタについては

public class Ipu4CalibraitionToolsLoader : BaseCalibrationToolsLoader 
{ 
    public Ipu4CalibraitionToolsLoader() 
     : base() // <- call the protected constructor 
    { 
     // put here the specific implementation constructor code 
     // notice that the constructor of the abstract class will **ALWAYS** be call before this code 
     _ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile()); 
    } 

    // The GetCmcGroupOrder is already implemented, nothing to do about it 

    // With the sealed keyword, the method cannot be overriden in another class 
    public sealed override void GetDefaultIsp(string selectedSensorType = null) 
    { 
     // put here the concrete implementation for Ipu4 
    } 
} 

public class Ipu6CalibraitionToolsLoader: BaseCalibrationToolsLoader 
{ 
    public Ipu6CalibraitionToolsLoader(string selectedSensorType) 
     : base() // <- call the protected constructor 
    { 
     // put here the specific implementation constructor code 
     // notice that the constructor of the abstract class will **ALWAYS** be call before this code 
     _selectedSensorType = selectedSensorType; 
     _ispSectionUiSettings = Serialization.DataContract.Deserialize<IspSectionUiSettings>(GetDefaultIspFile(_selectedSensorType)); 
    } 

    // The GetCmcGroupOrder is already implemented, nothing to do about it 

    // With the sealed keyword, the method cannot be overriden in another class 
    public sealed override void GetDefaultIsp(string selectedSensorType = null) 
    { 
     // put here the concrete implementation for Ipu6 
    } 
} 

を、あなたは抽象的で仮想メソッドを定義することができますこのクラスは、コードの一部を共有するために、具体的な実装でそれを呼び出す:

public abstract class BaseCalibrationToolsLoader : ICalibrationToolsLoader 
{ 
    [..] 

    // By using the virtual keyword, you allow your method to be overriden in the derived classes 
    public virtual void PartiallySharedMethod() 
    { 
     // Shared implementation 
    } 

    [..] 
} 

そして、具体的な実装で

public class Ipu4CalibraitionToolsLoader : BaseCalibrationToolsLoader 
{ 
    [..] 

    public override void PartiallySharedMethod() 
    { 
     // Unlike in the constructor, you can call the base method whenever you want. 
     // Some specific code can came here 
     base.PartiallySharedMethod(); 
     // And other specific code can also came here 
    } 

    [..] 
} 

public class Ipu6CalibraitionToolsLoader: BaseCalibrationToolsLoader 
{ 
    [..] 

    public override void PartiallySharedMethod() 
    { 
     // Unlike in the constructor, you can call the base method whenever you want. 
     // Some specific code can came here 
     base.PartiallySharedMethod(); 
     // And other specific code can also came here 
    } 

    [..] 
} 
+0

を追加しましたが、仮想関数の呼び出しをどのように解決するのか分かりません。 – Gilad

+0

私はあなたの仮想関数の内容を理解していません。それが共有コードであれば、それを抽象クラスコンストラクタに入れてください。実装固有のコードの場合は、それを関連付けられたコンストラクタに配置するだけです。 – fharreau

+0

それは共有コードではない、私はそれぞれの派生クラスのための同じ関数の特定の実装を持っている、これは私が仮想関数のようなものが必要な理由ですが、私はクラスをインスタンス。 – Gilad

関連する問題