如何在ColdFusion中设置.NET枚举

3
在下面展示的方式调用一个.Net对象(cfdump如下所示)...
<cfobject type=".NET" name="GoCardless" class="GoCardlessSdk.GoCardless" assembly="#expandpath("../GoCardlessSdk.dll")#,#expandpath("../Newtonsoft.Json.dll")#,#expandpath("../RestSharp.dll")#">

cfdump展示的.Net对象

现在我需要设置一个枚举。.Net的示例代码如下:

GoCardless.Environment = GoCardless.Environments.Sandbox;

下面是该类的C#代码:

using System;
using System.Collections.Generic;
using System.Reflection;
using GoCardlessSdk.Api;
using GoCardlessSdk.Connect;
using GoCardlessSdk.Helpers;
using GoCardlessSdk.Partners;

namespace GoCardlessSdk
{
    public static class GoCardless
    {
        static GoCardless()
        {
            AccountDetails = new AccountDetails();
        }

        public enum Environments
        {
            Production,
            Sandbox,
            Test
        }

        public static readonly Dictionary<Environments, string> BaseUrls =
            new Dictionary<Environments, string>
                {
                    {Environments.Production, "https://gocardless.com"},
                    {Environments.Sandbox, "https://sandbox.gocardless.com"},
                    {Environments.Test, "http://gocardless.com"}
                };

        private static string _baseUrl;

        public static string BaseUrl
        {
            get { return _baseUrl ?? BaseUrls[Environment ?? Environments.Production]; }
            set { _baseUrl = value.Trim(); }
        }

        public static Environments? Environment { get; set; }

        public static AccountDetails AccountDetails { get; set; }

        public static ApiClient Api
        {
        get { return new ApiClient(AccountDetails.Token); }
        }

        public static ConnectClient Connect
        {
            get { return new ConnectClient(); }
        }

        public static PartnerClient Partner
        {
            get { return new PartnerClient(); }
        }


        internal static string UserAgent = GetUserAgent();
        private static string GetUserAgent()
        {
            try
            {
                return "gocardless-dotnet/v" + GetAssemblyFileVersion();
            }
            catch
            {
                return "gocardless-dotnet";
            }
        }
        private static string GetAssemblyFileVersion()
        {
            Assembly assembly = Assembly.GetAssembly(typeof (GoCardless));
            var attributes = assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)
                    as AssemblyFileVersionAttribute[];

            if (attributes != null && attributes.Length == 1)
            {
                return attributes[0].Version;
            }
            return "";
        }

        private static Func<string> _generateNonce;
        internal static Func<string> GenerateNonce
        {
            get { return _generateNonce ?? (_generateNonce = Utils.GenerateNonce); }
            set { _generateNonce = value; }
        }

        private static Func<DateTimeOffset> _getUtcNow; 
        internal static Func<DateTimeOffset> GetUtcNow
        {
            get { return _getUtcNow ?? (_getUtcNow = () => DateTimeOffset.UtcNow); }
            set { _getUtcNow = value; }
        } 
    }
    }

请问有人能够向我解释如何在ColdFusion中设置枚举吗?

谢谢!

更新

针对Leigh的实用类解决方案,我的代码如下:

<cfscript>

    GoCardless = createObject(".net", "GoCardlessSdk.GoCardless","path to GoCardless DLL,paths to supporting DLLs");

    Environments = createObject(".net", "GoCardlessSdk.GoCardless$Environments", "path to GoCardless DLL");

    util = createObject(".net", "GoCardlessSdk.GoCardlessSdkUtil", "path to utility DLL");

    dumps etc...

</cfscript>

如果我删除最后一个createobject()调用,则前两个将完美运行。即使在所有createobject()调用中包括所有DLL的路径,我仍然会得到相同的错误。
1个回答

4

(免责声明:我的当前测试环境是CF9,但结果与您的相同)

通常情况下,您可以使用set_FieldName( value )来修改字段。但是,我从您的截图中发现该方法不存在。我不确定原因,所以进行了一些搜索。根据我所读的内容,您的类正在使用可空类型

    public static Environments? Environment { get; set; }

似乎这是问题的根源。据我所知,jnbridge(用于 .net 互操作的基础工具)在涉及可空类型时不会生成代理。这就解释了为什么访问 Evironment 字段的方法丢失了。如果去掉 ? 运算符,它就可以正常工作。 < p > CF 代码:
<cfscript>
    goCardless = createObject(".net", "GoCardlessSdk.GoCardless", ExpandPath("./GoCardlessSdk.dll"));
    Environments = createObject(".net", "GoCardlessSdk.GoCardless$Environments", ExpandPath("./GoCardlessSdk.dll"));
    goCardLess.set_Environment(Environments.Test);
    writeDump( goCardLess.get_Environment().toString() );
</cfscript>

测试类:(不带可空类型)

namespace GoCardlessSdk
{
    public static class GoCardless
    {
        static GoCardless()
        {
        }

        public enum Environments
        {
            Production,
            Sandbox,
            Test
        }

        public static Environments Environment { get; set; }
    }
}

更新 1:

  • 因此,修改类以消除 Nullable 类型是一种选择。
  • 另一个可能性是手动生成代理。 jnbridge 还存在.net 泛型问题,因此自己生成代理可能会起作用。
  • 第三种可能性是编写帮助程序类,不使用 Nullable 类型设置/获取值。这有点像黑客行为,但确实有效。

更新 2/3:

以下是一个简单辅助类的粗略示例。如果您想要帮助者的 get 方法返回 null(与原始方法相同),则使用 getNullableEnvironment。如果您希望返回默认值而不是 null,则使用 getEnvironment。至于设置方面,我所做的都只有:

  • 在 VS 中创建了一个新解决方案
  • 添加了对 GoCardlessSDK.dll 的引用

<cfscript>
   dllPaths = arrayToList( [ ExpandPath("GoCardlessUtil.dll")
                            , ExpandPath("GoCardlessSdk.dll")
                            , ExpandPath("Newtonsoft.Json.dll")
                            , ExpandPath("RestSharp.dll")
                            ]
                        );
    goCardless = createObject(".net", "GoCardlessSdk.GoCardless", dllPaths);
    Environments = createObject(".net", "GoCardlessSdk.GoCardless$Environments", dllPaths);
    util = createObject(".net", "GoCardlessUtil.GoCardlessSdkUtil", dllPaths );
    WriteDump("before="& util.getNullableEnvironment());
    util.setEnvironment(Environments.Production);
    WriteDump("after="& util.getNullableEnvironment().toString());
</cfscript> 

GoCardlessSdkUtil.cs

using System;
using System.Collections.Generic;
using System.Text;
using GoCardlessSdk;

namespace GoCardlessUtil
{
    public class GoCardlessSdkUtil
    {
        public static void setEnvironment(GoCardless.Environments environ)
        {
            GoCardless.Environment = environ;
        }

        /*
        // Enum's cannot be null. So we are applying a default
        // value ie "Test" instead of returning null
        public static GoCardless.Environments getEnvironment()
        {
            return GoCardless.Environment.HasValue ? GoCardless.Environment.Value : GoCardless.Environments.Test;
        }
        */

        // This is the closest to the original method
        // Since enum's cannot be null, we must return type Object instead of Environment
        // Note: This will return be null/undefined the first time it is invoked
        public static Object getNullableEnvironment()
        {
            return GoCardless.Environment;
        }
    }
}

你能解释一下我该如何进行第三个选项吗?谢谢 :) - Michael
感谢您抽出时间来做这件事,Leigh。不幸的是,当我运行上面的代码时,我遇到了“在指定的程序集列表中找不到GoCardlessSdk.GoCardlessSdkUtil类”的错误。 - Michael
它在上面的示例类中运行良好。虽然我还没有使用单独的dll进行测试,例如gocardless.dll + utility.dll)愚蠢的问题是,您是否将utility dll附加到程序集列表中?换句话说,您必须在程序集列表中包含两个 dll,以便在所有 createobject 调用中使用。 - Leigh
@MichaelHenson - 我成功创建了一个独立的项目,添加了对gocardless.dll的引用,并且似乎对我来说工作得很好。(注意:我更改了辅助项目名称)。请查看我的更新答案。 - Leigh
同样的错误,我很抱歉。也许它没有正确编译。你是如何编译C#代码的?我是使用以下命令行调用的:'csc /t:library GoCardlessSdkUtil.cs -> GoCardlessSdkUtil.dll'。 - Michael
让我们在聊天中继续这个讨论 - Leigh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接