如何在动态类型上执行字符串路径?

发布于 2024-10-14 15:25:39 字数 294 浏览 1 评论 0原文

是否可以在动态类型上执行字符串路径?

例如,我们可以编写动态类型

dynamic d = myObj;
var v = d.MyMethod(1,"text").SomeProperty.Name

现在假设我有字符串路径

string path = "MyMethod(1,\"text\").SomeProperty.Name";
var v = d. //How to applay string path to this type?

Is it possible to execute string path on dynamic type?

For example having dynamic type we can write

dynamic d = myObj;
var v = d.MyMethod(1,"text").SomeProperty.Name

Now imagine I have string path

string path = "MyMethod(1,\"text\").SomeProperty.Name";
var v = d. //How to applay string path to this type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小…红帽 2024-10-21 15:25:39

我有使用扩展方法和反射的解决方案,您需要针对不同的场景进行优化和测试。

编辑
仍然是脏代码,但现在支持重载方法。我将尝试进行代码清理并使用正则表达式来获得有效且更干净的解决方案

您现在可以为 eval 方法指定参数的数据类型。

string epath = "GetName(System_String: ding dong, System_Int32:1).name";
MyClass cls = new MyClass();
var v = cls.Eval(epath);

请注意类型名称中的下划线。如果方法没有重载,这应该可以在不提及数据类型的情况下工作。当前限制,您不能在字符串参数值内使用冒号或逗号。 :(

调用 var v = d.Execute(path)

        public static object Eval(this object instance, string path)
    {
        string[] cmd = path.Split('.');
        string subString = cmd[0];
        object returnValue = null;
        Type t = instance.GetType();
        if (subString.Contains("("))
        {
            string[] paramString = subString.Split('(');
            string[] parameters = paramString[1].Replace(")", "").Split(new Char[]{','},StringSplitOptions.RemoveEmptyEntries);
            bool hasNoParams = parameters.Length == 0;

            List<Type> typeArray = null;
            if (hasNoParams) typeArray = new List<Type>();
            foreach (string parameter in parameters)
            {
                if (parameter.Contains(":"))
                {
                    if (typeArray == null) typeArray = new List<Type>();
                    string[] typeValue = parameter.Split(':');
                    Type paramType = Type.GetType(typeValue[0].Replace('_','.'));

                    typeArray.Add(paramType);
                }
            }
            MethodInfo info = null;
            if (typeArray == null)
                info = t.GetMethod(paramString[0]);
            else
                info = t.GetMethod(paramString[0], typeArray.ToArray());
            ParameterInfo[] pInfo = info.GetParameters();
            List<object> paramList = new List<object>();
            for (int i = 0; i < pInfo.Length; i++)
            {
                string currentParam = parameters[i];
                if (currentParam.Contains(":"))
                {
                    currentParam = currentParam.Split(':')[1];
                }
                ParameterInfo pram = pInfo[i];
                Type pType = pram.ParameterType;
                object obj = Convert.ChangeType(currentParam, pType);
                paramList.Add(obj);
            }
            if (info == null) returnValue = null;
            else
                returnValue = info.Invoke(instance, paramList.ToArray());
        }
        else
        {

            PropertyInfo pi = t.GetProperty(subString);
            if (pi == null) returnValue = null;
            else
                returnValue = pi.GetValue(instance, null);
        }
        if (returnValue == null || cmd.Length == 1)
            return returnValue;
        else
        {
            returnValue = returnValue.Eval(path.Replace(cmd[0] + ".", ""));
        }
        return returnValue;
    }

I have solution using extension method and reflection, you need to optimize and test for different scenario.

EDIT
Still dirty code, but supports overloaded method now. I will try to do code clean up and use regex for effective and cleaner solution

You can specify data types for parameters now to the eval method.

string epath = "GetName(System_String: ding dong, System_Int32:1).name";
MyClass cls = new MyClass();
var v = cls.Eval(epath);

Note underscore in type names. This should work without mentioning datatypes if method are not overloaded. Current restriction, you cannot use colon or comma inside string parameter value. :(

Call like var v = d.Execute(path)

        public static object Eval(this object instance, string path)
    {
        string[] cmd = path.Split('.');
        string subString = cmd[0];
        object returnValue = null;
        Type t = instance.GetType();
        if (subString.Contains("("))
        {
            string[] paramString = subString.Split('(');
            string[] parameters = paramString[1].Replace(")", "").Split(new Char[]{','},StringSplitOptions.RemoveEmptyEntries);
            bool hasNoParams = parameters.Length == 0;

            List<Type> typeArray = null;
            if (hasNoParams) typeArray = new List<Type>();
            foreach (string parameter in parameters)
            {
                if (parameter.Contains(":"))
                {
                    if (typeArray == null) typeArray = new List<Type>();
                    string[] typeValue = parameter.Split(':');
                    Type paramType = Type.GetType(typeValue[0].Replace('_','.'));

                    typeArray.Add(paramType);
                }
            }
            MethodInfo info = null;
            if (typeArray == null)
                info = t.GetMethod(paramString[0]);
            else
                info = t.GetMethod(paramString[0], typeArray.ToArray());
            ParameterInfo[] pInfo = info.GetParameters();
            List<object> paramList = new List<object>();
            for (int i = 0; i < pInfo.Length; i++)
            {
                string currentParam = parameters[i];
                if (currentParam.Contains(":"))
                {
                    currentParam = currentParam.Split(':')[1];
                }
                ParameterInfo pram = pInfo[i];
                Type pType = pram.ParameterType;
                object obj = Convert.ChangeType(currentParam, pType);
                paramList.Add(obj);
            }
            if (info == null) returnValue = null;
            else
                returnValue = info.Invoke(instance, paramList.ToArray());
        }
        else
        {

            PropertyInfo pi = t.GetProperty(subString);
            if (pi == null) returnValue = null;
            else
                returnValue = pi.GetValue(instance, null);
        }
        if (returnValue == null || cmd.Length == 1)
            return returnValue;
        else
        {
            returnValue = returnValue.Eval(path.Replace(cmd[0] + ".", ""));
        }
        return returnValue;
    }
∝单色的世界 2024-10-21 15:25:39

看来你需要一个 eval 函数,而 C# 没有,但是如果这个第三方C# eval 实现 可以处理动态 它可能会解决您的问题。

It seems you would need an eval function and C# has none but if this third party C# eval implementation can handle dynamic it might solve your problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文