SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

C++/CLIで、機能拡張を簡単に実現するフレームワーク「MEF」を試してみた

re-buildなしに機能拡張!

interfaceの定義とその実装

 それではMEFを使った拡張機能をこしらえましょうか。

 まずはinterfaceから。定義するinterfaceは、

  • intを2つ与えるとintを返す演算:IOperation
  • 演算に付けられた演算子(の名前):IOperationData
  • 2つのintと演算子を与えると演算子に応じた演算を行って結果を返す計算機:ICalculator

の3つです。

Interface.h
#ifndef INTERFACE_H_
#define INTERFACE_H_

namespace SimpleCalculator {

  public interface class IOperation {
    int Operate(int left, int right);
  };

  public interface class IOperationData {
    property System::String^ Symbol { System::String^ get(); }
  };

  public interface class ICalculator {
    int Calculate(int left, System::String^ opr, int right);
    System::Collections::Generic::IEnumerable<System::String^>^ Symbols();
  };

}

#endif

 IOperationの実装は、ひとまず加算:Addと減算:Subtractの2つを用意しましょう。

Operations.cpp
#include "Interface.h"

using namespace System::ComponentModel::Composition;

namespace SimpleCalculator {

  [Export(IOperation::typeid)]
  [ExportMetadata(L"Symbol", L"+")]
  ref class Add : IOperation {
  public:
    virtual int Operate(int left, int right) {
      return left + right;
    }
  };

  [Export(IOperation::typeid)]
  [ExportMetadata(L"Symbol", L"-")]
  ref class Subtract : IOperation {
  public: 
    virtual int Operate(int left, int right) {
      return left - right;
    }
  };
 
}

 ここでのキモは[]で囲まれたアトリビュートです。「Add/SubtractはIOpertationを実装し、不可情報:Symbolを"+"/"-"としてExport(公開)する」ことを表しています。

 そしてICalculatorを実装したCalculator:

Calculator.cpp
#include "Interface.h"

using namespace System;
using namespace System::ComponentModel::Composition;
using namespace System::Collections::Generic;

namespace SimpleCalculator {

  [Export(ICalculator::typeid)]
  ref class Calculator : ICalculator {
  private:
    [ImportMany]
    IEnumerable<System::Lazy<IOperation^, IOperationData^>^>^ operations_;

  public:
    // Symbolが一致するIOperationを見つけ、実行する
    virtual int Calculate(int left, System::String^ operation, int right) {
      for each (Lazy<IOperation^, IOperationData^>^ item in operations_) {
        if ( item->Metadata->Symbol == operation ) 
          return item->Value->Operate(left, right);
      }
      throw gcnew NotSupportedException(operation);
    }

    // Symbolの列挙を返す
    virtual IEnumerable<System::String^>^ Symbols() {
      auto result = gcnew List<String^>();
      for each (Lazy<IOperation^, IOperationData^>^ item in operations_) {
        result->Add(item->Metadata->Symbol);
      }
      return result;      
    }

  };

}

 メンバ変数operations_は、IOperationとIOperationDataの組を複数個(演算の数だけ)抱えます。アトリビュート[ImportMany]に注目、MEFはこのアトリビュートが付けられた変数に[Export(IOperation::typeid)]な複数のclassを結び付けてくれます。

 メソッドOperate()は、operations_に納められたIOperationとIOperationDataの組を使って演算子に応じたIOperationを見つけて演算を行いますし、Symbols()は登録されている演算子の列挙を返します。

次のページ
フォームに組み込む

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/7738 2014/06/05 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー