/////////////////////////////////////////////////////////////////////
// AttribDef.h - demonstrates how to create {Developer] attribute  //
//                                                                 //
// Jim Fawcett, CSE775 - Distributed Objects, Spring 2003          //
/////////////////////////////////////////////////////////////////////
// Build Process:
//
// Required Files:
//   AttribDef.h, AttribDef.cpp, Stdafx.h, Stdafx.h, 
//   AssemblyInfo.cpp
//
// To Build:
//   right click on project and select build
/////////////////////////////////////////////////////////////////////

#pragma once

using namespace System;
using namespace System::Reflection;

namespace AttribDef
{
[AttributeUsage(AttributeTargets::All)]
public ref class DeveloperAttribute : public Attribute
  {
  public:
    DeveloperAttribute(String^ name)
      : m_Name(name) {}

    property String^ Developer
    {
      String^ get()
      {
        return m_Name;
      }
    }
  
  private:
    String^ m_Name;
  };
}
// This is the main DLL file.

#include "stdafx.h"

#include "AttribDef.h"

/////////////////////////////////////////////////////////////////
// AttribLib.h - demonstrates how to use {Developer] attribute //
//                                                             //
// Jim Fawcett, CSE775 - Distributed Objects, Spring 2003      //
/////////////////////////////////////////////////////////////////
// Build Process:
//
// Required Files:
//   AttribLib.h, AttribLib.cpp, Stdafx.h, Stdafx.h, 
//   AssemblyInfo.cpp, AttribDef.dll
//
// To Build:
//   - AttribDef.dll needs to be in the AttribLib\debug folder
//   - build
/////////////////////////////////////////////////////////////////

#pragma once

using namespace System;
using namespace System::Text;
#using "../AttribDef/Debug/AttribDef.dll"
using namespace AttribDef;

namespace AttribLib
{
  [DeveloperAttribute("Jim Fawcett")]
  public ref class Test
  {
  public:
    String^ say()
    {
      StringBuilder^ pTemp = gcnew StringBuilder("a test case for ");
      pTemp->Append(getDeveloper());
      return pTemp->ToString();
    }
    //----< extract developer name from metadata >-------------------

    String^ getDeveloper()
    {
      Type^ pType = GetType();
      array<Attribute^>^ pObjs = Attribute::GetCustomAttributes(pType);
      for(int i=0; i<pObjs->Length; ++i)
      {
        if(pObjs[i]->GetType()->Equals(DeveloperAttribute::typeid))
        {
          String^ dev = static_cast<DeveloperAttribute^>(pObjs[i])->Developer;
          return dev;
        }
      }
      return "not found";
    }
  };
}
// This is the main DLL file.

#include "stdafx.h"

#include "AttribLib.h"

/////////////////////////////////////////////////////////////////
// AttribProgram.cpp - demonstrate use of custom attribute     //
//                                                             //
// Jim Fawcett, CSE775 - Distributed Objects, Spring 2003      //
/////////////////////////////////////////////////////////////////
// Build Process:
//
// Required Files:
//   AttribProgram.cpp, AttribLib.dll, AttribDef.dll
//
// To Build:
//   - compile and run.
//   - For running AttribDef.dll and AttribLib.dll need to be
//     copied into the AttribProgram Project debug folder.
/////////////////////////////////////////////////////////////////

//#using <mscorlib.dll>
using namespace System;

#using "../AttribDef/Debug/AttribDef.dll"       // defines DeveloperAttribute
using namespace AttribDef;

#using "../AttribLib/Debug/AttribLib.dll"       // uses DeveloperAttribute
using namespace AttribLib;

#include <iostream>
using namespace std;

//----< extract developer name from metadata >-------------------

String^ getDeveloper()
{
  Type^ pType = Test::typeid;
  array<Attribute^>^ pObjs = Attribute::GetCustomAttributes(pType);
  Console::Write("\n  Test has {0} attribute(s)",pObjs->Length);
  for(int i=0; i<pObjs->Length; ++i)
  {
    if(pObjs[i]->GetType()->Equals(DeveloperAttribute::typeid))
    {
      Console::Write("\n  found developer");
      String^ dev = static_cast<DeveloperAttribute^>(pObjs[i])->Developer;
      return dev;
    }
  }
  return "not found";
}

//----< test stub >----------------------------------------------

int main()
{
  Console::Write("\n  Testing Custom Attribute Definition and Use");
  Console::Write("\n =============================================\n");

  // use attributed library

  Test^ pTest = gcnew Test();
  Console::WriteLine("\n  Library result: {0}",pTest->say());
  
  // display DeveloperAttribute

  String^ dev = getDeveloper();
  Console::WriteLine("\n  developer is: {0}\n\n",dev);
}
