blob: 383df025596572412afa28908239cbc80029b8c2 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
#pragma once
#include "../gf_defs.hpp"
//#include "../SerializableM.hpp"
#include "ManagedCacheableKey.hpp"
#include "SafeConvert.hpp"
#include "../LogM.hpp"
using namespace System;
namespace GemStone
{
namespace GemFire
{
namespace Cache
{
/// <summary>
/// Template class to wrap a managed <see cref="TypeFactoryMethod" />
/// delegate that returns an <see cref="IGFSerializable" /> object. It contains
/// a method that converts the managed object gotten by invoking the
/// delegate to the native <c>gemfire::Serializable</c> object
/// (using the provided wrapper class constructor).
/// </summary>
/// <remarks>
/// This class is to enable interopibility between the managed and unmanaged
/// worlds when registering types.
/// In the managed world a user would register a managed type by providing
/// a factory delegate returning an object of that type. However, the
/// native implementation requires a factory function that returns an
/// object implementing <c>gemfire::Serializable</c>. Normally this would not
/// be possible since we require to dynamically generate a new function
/// for a given delegate.
///
/// Fortunately in the managed world the delegates contain an implicit
/// 'this' pointer. Thus we can have a universal delegate that contains
/// the given managed delegate (in the 'this' pointer) and returns the
/// native <c>gemfire::Serializable</c> object. Additionally marshalling
/// services provide <c>Marshal.GetFunctionPointerForDelegate</c> which gives
/// a function pointer for a delegate which completes the conversion.
/// </remarks>
ref class DelegateWrapper
{
public:
/// <summary>
/// Constructor to wrap the given managed delegate.
/// </summary>
inline DelegateWrapper( TypeFactoryMethod^ typeDelegate )
: m_delegate( typeDelegate ) { }
/// <summary>
/// Returns the native <c>gemfire::Serializable</c> object by invoking the
/// managed delegate provided in the constructor.
/// </summary>
/// <returns>
/// Native <c>gemfire::Serializable</c> object after invoking the managed
/// delegate and wrapping inside a <c>ManagedCacheableKey</c> object.
/// </returns>
gemfire::Serializable* NativeDelegate( )
{
IGFSerializable^ tempObj = m_delegate( );
IGFDelta^ tempDelta = dynamic_cast<IGFDelta^>(tempObj);
if( tempDelta != nullptr )
{
if(!SafeConvertClass::isAppDomainEnabled)
return new gemfire::ManagedCacheableDelta( tempDelta );
else
return new gemfire::ManagedCacheableDeltaBytes( tempDelta, false );
}
else if(!SafeConvertClass::isAppDomainEnabled)
return new gemfire::ManagedCacheableKey( tempObj, 0, tempObj->ClassId);
else
return new gemfire::ManagedCacheableKeyBytes( tempObj, false);
}
private:
TypeFactoryMethod^ m_delegate;
};
}
}
}