Как выполнить путь строки на динамический тип? - PullRequest
4 голосов
/ 26 января 2011

Возможно ли выполнить путь строки в динамическом типе?

Например, имея динамический тип, мы можем написать

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?

Ответы [ 3 ]

2 голосов
/ 26 января 2011

У меня есть решение с использованием метода расширения и отражения, вам необходимо оптимизировать и протестировать его для другого сценария.

EDIT Все еще грязный код, но теперь поддерживает перегруженный метод. Я постараюсь очистить код и использовать регулярные выражения для эффективного и чистого решения

Теперь вы можете указать типы данных для параметров в методе 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;
    }
1 голос
/ 26 января 2011

Кажется, вам понадобится функция eval, а в C # ее нет, но если эта сторонняя реализация C # eval может обработать dynamic, это может решить вашу проблему.

1 голос
/ 26 января 2011

Не уверен, что это может быть легко достигнуто.Я использовал Spring.NET Expressions в прошлом.

...