/// <summary> /// Returns the Cadence activity type name to be used for a activity interface or /// implementation class. /// </summary> /// <param name="activityType">The activity interface or implementation type.</param> /// <param name="activityAttribute">Specifies the <see cref="ActivityAttribute"/>.</param> /// <returns>The type name.</returns> /// <remarks> /// <para> /// If <paramref name="activityAttribute"/> is passed and <see cref="ActivityAttribute.Name"/> /// is not <c>null</c> or empty, then the name specified in the attribute is returned. /// </para> /// <para> /// Otherwise, we'll return the fully qualified name of the activity interface /// with the leadting "I" removed. /// </para> /// </remarks> internal static string GetActivityTypeName(Type activityType, ActivityAttribute activityAttribute) { Covenant.Requires <ArgumentNullException>(activityType != null, nameof(activityType)); if (activityAttribute != null && !string.IsNullOrEmpty(activityAttribute.Name)) { return(activityAttribute.Name); } if (activityType.IsClass) { CadenceHelper.ValidateActivityImplementation(activityType); activityType = CadenceHelper.GetActivityInterface(activityType); } else { CadenceHelper.ValidateActivityInterface(activityType); } var fullName = activityType.FullName; var name = activityType.Name; if (name.StartsWith("I") && name != "I") { // We're going to strip the leading "I" from the unqualified // type name (unless that's the only character). fullName = fullName.Substring(0, fullName.Length - name.Length); fullName += name.Substring(1); } // We need to replace the "+" characters .NET uses for nested types into // "." so the result will be a valid C# type identifier. return(fullName.Replace('+', '.')); }
/// <summary> /// Returns the activity type and method information for an activity interface and /// an optional target method name. /// </summary> /// <param name="activityInterface">The target activity interface.</param> /// <param name="methodName"> /// Optionally specifies the target method name (as specified in the <c>[ActivityMethod]</c> /// attribiute tagging the activity method within the interface. /// </param> /// <returns>The activity type name for the activity interface as well as the method information and attribute.</returns> /// <exception cref="ArgumentException">Thrown if target method does not exist.</exception> /// <remarks> /// <paramref name="methodName"/> is optional. When this is passed as <c>null</c> /// or empty, the default activity method will be targeted (if any). /// </remarks> internal static (string ActivityTypeName, MethodInfo TargetMethod, ActivityMethodAttribute MethodAttribute) GetActivityTarget(Type activityInterface, string methodName = null) { Covenant.Requires <ArgumentNullException>(activityInterface != null); CadenceHelper.ValidateActivityInterface(activityInterface); var activityAttribute = activityInterface.GetCustomAttribute <ActivityAttribute>(); var methodAttribute = (ActivityMethodAttribute)null; var targetMethod = (MethodInfo)null; if (string.IsNullOrEmpty(methodName)) { // Look for the entrypoint method with a null or empty method name. foreach (var method in activityInterface.GetMethods()) { methodAttribute = method.GetCustomAttribute <ActivityMethodAttribute>(); if (methodAttribute != null) { if (string.IsNullOrEmpty(methodAttribute.Name)) { targetMethod = method; break; } } } } else { // Look for the entrypoint method with the matching method name. foreach (var method in activityInterface.GetMethods()) { methodAttribute = method.GetCustomAttribute <ActivityMethodAttribute>(); if (methodAttribute != null) { if (methodName == methodAttribute.Name) { targetMethod = method; break; } } } } if (targetMethod == null) { throw new ArgumentException($"Activity interface [{activityInterface.FullName}] does not have a method tagged by [ActivityMethod(Name = {methodName})].", nameof(activityInterface)); } var activityTypeName = CadenceHelper.GetActivityTypeName(activityInterface, activityAttribute); if (!string.IsNullOrEmpty(methodAttribute.Name)) { activityTypeName += $"::{methodAttribute.Name}"; } return(activityTypeName, targetMethod, methodAttribute); }