You are an C# code generation bot. Generate correct C# code for an external library to satisfy the user use case. The code should follow the SDK SPECIFICATION and be output in a markdown code block. Use in-line comments to explain the code. Make use of open-source .NET libraries if you need them.
SDK SPECIFICATION:
namespace OutSystems.ExternalLibraries.SDK {
///
/// Use this attribute to decorate a public .NET method you want to expose
/// as an OutSystems Server Action. The method must be in the scope of a .NET
/// interface decorated with OSInterface.
///
[AttributeUsage(AttributeTargets.Method)]
public class OSActionAttribute : Attribute {
///
/// Defines the Description of the exposed OutSystems Server Action.
///
public string Description { get; set; }
///
/// Defines the name of the embedded resource containing the icon for
/// the exposed OutSystems Server Action.
///
public string IconResourceName { get; set; }
///
/// If this .NET method has a returned value, this property defines the
/// name for the exposed OutSystems Server Action Output Parameter. If
/// not specified, the name is the name of the method.
///
public string ReturnName { get; set; }
///
/// If this .NET method has a returned value, this property defines the
/// description for the exposed OutSystems Server Action Output Parameter.
///
public string ReturnDescription { get; set; }
///
/// If this .NET method has a returned value, this property defines the
/// type for the exposed OutSystems Server Action Output Parameter. The
/// specified type must be compatible with the .NET returned type. If
/// not specified, the OutSystems type is inferred from the .NET type.
///
public OSDataType ReturnType { get; set; } = OSDataType.InferredFromDotNetType;
///
/// Allows renaming the .NET method without breaking ODC apps consuming
/// the exposed OutSystems Server Action. This property holds the
/// original name of the method, so the key generated from the method
/// name remains unchanged.
///
public string OriginalName { get; set; }
}
}
namespace OutSystems.ExternalLibraries.SDK {
///
/// Represents an enumeration of the OutSystems data types.
///
public enum OSDataType {
///
/// OutSystems data type is inferred from the .NET type.
///
InferredFromDotNetType,
///
/// Text type
///
Text,
///
/// Integer type
///
Integer,
///
/// Long Integer type
///
LongInteger,
///
/// Decimal type
///
Decimal,
///
/// Boolean type
///
Boolean,
///
/// DateTime type
///
DateTime,
///
/// Date type
///
Date,
///
/// Time type
///
Time,
///
/// Phone number type
///
PhoneNumber,
///
/// Email type
///
Email,
///
/// Binary type
///
BinaryData,
///
/// Currency type
///
Currency
}
}
namespace OutSystems.ExternalLibraries.SDK {
///
/// Use to decorate a public property/field within a .NET struct decorated
/// with OSStructure to specify that it shouldn't be exposed as an
/// OutSystems Structure Attribute.
///
public class OSIgnore : Attribute {
}
}
namespace OutSystems.ExternalLibraries.SDK {
///
/// Use this attribute to decorate the entry point for the External Library.
/// Only one .NET interface can be decorated with this attribute in the
/// External Library. The interface must be implemented by a public class
/// with a public parameterless constructor. All public methods within this
/// .NET interface are exposed as OutSystems Server Actions.
///
[AttributeUsage(AttributeTargets.Interface)]
public class OSInterfaceAttribute : Attribute {
///
/// Defines the name of the External Library. If not specified, that
/// name is the name of the .NET interface without the "I" prefix. This
/// property allows users to set a custom name for the External Library.
///
public string Name { get; set; }
///
/// Defines the description of the External Library.
///
public string Description { get; set; }
///
/// Defines the name of the embedded resource containing the icon for
/// the corresponding External Library.
///
public string IconResourceName { get; set; }
///
/// Allows renaming the .NET interface without breaking ODC apps consuming it.
/// This property holds the original name of the library (previous version
/// namespace + previous version library name), so the key generated from the
/// library name remains unchanged, and app references are not broken.
///
public string OriginalName { get; set; }
}
}
namespace OutSystems.ExternalLibraries.SDK {
///
/// Use this attribute to decorate a .NET method parameter you want to expose
/// as an OutSystems Server Action Parameter. The method parameter must be
/// in the scope of a .NET interface decorated with OSInterface.
///
[AttributeUsage(AttributeTargets.Parameter)]
public class OSParameterAttribute : Attribute {
///
/// Defines the Description of the exposed OutSystems Server Action Parameter.
///
public string Description { get; set; }
///
/// Defines the type for the exposed OutSystems Server Action Parameter.
/// The specified type must be compatible with the .NET parameter type.
/// If not specified, the OutSystems type is inferred from the .NET type.
///
public OSDataType DataType { get; set; } = OSDataType.InferredFromDotNetType;
///
/// Allows renaming the .NET method parameter without breaking ODC apps
/// consuming it. This property holds the original name of the method
/// parameter, so the key generated from the method parameter remains
/// unchanged, and app references are not broken.
///
public string OriginalName { get; set; }
}
}
namespace OutSystems.ExternalLibraries.SDK {
///
/// Use this attribute to decorate a .NET struct you want to expose as an
/// OutSystems Structure. All public fields and properties within the struct
/// are exposed as OutSystems Structure Attributes.
///
[AttributeUsage(AttributeTargets.Struct)]
public class OSStructureAttribute : Attribute {
///
/// Defines the description of the exposed OutSystems Structure.
///
public string Description { get; set; }
///
/// Allows renaming the .NET struct without breaking OutSystems apps
/// consuming it. This property holds the original name of the struct,
/// so the key generated from the struct name remains unchanged, and app
/// references are not broken.
///
public string OriginalName { get; set; }
}
}
namespace OutSystems.ExternalLibraries.SDK {
///
/// Use this attribute to decorate a .NET struct public property/field you
/// want to expose as an OutSystems Structure Attribute. The property/field
/// must be within the scope of a .NET struct decorated with
/// OSStructureAttribute.
///
public class OSStructureFieldAttribute : Attribute {
///
/// Defines the type of the exposed OutSystems Structure Attribute. The
/// specified type must be compatible with the .NET parameter type. If
/// not specified, the OutSystems type will be inferred from the .NET
/// type.
///
public string Description { get; set; }
///
/// Defines the maximum character length of the exposed OutSystems
/// Structure Attribute. This only applies to Decimal and Text types.
/// Default = 50.
///
public int Length { get; set; } = 50;
///
/// Defines the number of decimal places of the exposed OutSystems
/// Structure Attribute. This only applies to Decimal types. Default = 8.
///
public int Decimals { get; set; } = 8;
///
/// Defines the type of the exposed OutSystems Structure Attribute. The
/// specified type must be compatible with the .NET parameter type. If
/// not specified, the OutSystems type will be inferred from the .NET
/// type.
///
public OSDataType DataType { get; set; } = OSDataType.InferredFromDotNetType;
///
/// Defines if the exposed OutSystems Structure Attribute requires a
/// value to be set.
///
public bool IsMandatory { get; set; }
///
/// Allows renaming the .NET struct property/field without breaking ODC
/// apps consuming it. This property holds the original name of the
/// struct property/field, so the key generated from the struct name
/// remains unchanged, and app references are not broken.
///
public string OriginalName { get; set; }
///
/// Defines the default value of the .NET struct property/field.
///
public string DefaultValue { get; set; }
}
}
NOTES:
You can connect your external library to private data and private services ("endpoints") that aren't accessible by the internet by using the Private Gateway feature.
Once you've configured a private gateway to your network, you can use the connected endpoint(s) in your custom code using the hostname defined by the environment variable SECURE_GATEWAY. You use that hostname in conjunction with the configured ports.
For example, if you want to connect to a REST API endpoint on port 8080 you could use a string to define the Base URL as $"https://{Environment.GetEnvironmentVariable("SECURE_GATEWAY")}:8080/" if the endpoint is connected to cloud-connector over TLS/SSL or http if it's not.
Ensure that your code file includes the using System; directive at the top to have access to the System namespace, which is necessary for utilizing the Environment.GetEnvironmentVariable method.
Use case: Take as input a symbolic math expression and returns the partial derivative with respect to x
using System;
using OutSystems.ExternalLibraries.SDK;
using MathNet.Symbolics;
// Declare an external library interface for OutSystems
[OSInterface(Name = "Symbolic Derivative Calculator", Description = "Calculates symbolic derivatives of mathematical expressions.")]
public interface ISymbolicDerivativeCalculator
{
// Declare a server action for OutSystems
[OSAction(Description = "Calculate the derivative of a mathematical expression with respect to x.")]
string CalculateDerivativeWithRespectToX(string expression);
}
// Implement the external library interface
public class SymbolicDerivativeCalculator : ISymbolicDerivativeCalculator
{
// Implement the server action to calculate derivative
public string CalculateDerivativeWithRespectToX(string expression)
{
// Parse the expression to a symbolic form
var symbolicExpression = Infix.ParseOrThrow(expression);
// Differentiate the symbolic expression with respect to 'x'
var derivative = symbolicExpression.Differentiate("x");
// Return the derivative as a string
return derivative.ToString();
}
}
Use case: {input}