Esempio n. 1
0
        private List <string> BuildBinderHost(BuildStackTrace trace, PBinderHost rootHost)
        {
            var parameterLines = new List <string>();

            // 연결된 파라미터 바인더 가져옴
            foreach (var expression in rootHost
                     .GetExpressions()
                     .Where(e => e.Direction == BindDirection.Input && e.Input.BindOption == BindOptions.Parameter))
            {
                var host = expression.Output.Host as PBinderHost;

                // 파라미터 역전파로 트리거에 도달하는 경우
                // 무조건 sender를 가져옴
                if (host is PTrigger)
                {
                    DXMappingResult result = buildImpl(trace, host, "{Target}");

                    parameterLines.Add(result.Source);
                }
                else if (host.HasAttribute <TAttribute>())
                {
                    var attr = host.GetAttribute <TAttribute>();

                    DXMappingResult result = buildImpl(trace, host, attr.MappingCode);

                    parameterLines.Add(result.Source);
                }
            }

            return(parameterLines);
        }
Esempio n. 2
0
        private bool BuildParam(BuildStackTrace trace, DXMappingResult result, DXToken token, object obj, StringBuilder sourceBuilder)
        {
            if (obj is PFunction func)
            {
                string             paramName = token.Parameters[0];
                NamedParameterInfo pi        = func.ParameterInfos.FirstOrDefault(p => p.Name == paramName);

                if (pi != null)
                {
                    int       idx     = Array.IndexOf(func.ParameterInfos, pi);
                    IBinder[] binders = func.Items.Find(BindOptions.Parameter).ToArray();

                    if (binders.Length > idx)
                    {
                        string source = BuildBinder(trace, result, binders[idx] as PBinder);

                        sourceBuilder.Replace(
                            token.OriginalSource,
                            source);
                    }
                }
            }
            return(false);
        }
Esempio n. 3
0
        private bool BuildTarget(BuildStackTrace trace, DXMappingResult result, DXToken token, object obj, StringBuilder source)
        {
            bool isMultiline   = false;
            var  targetVisuals = new List <PVisual>();

            if (obj is PTrigger trigger)
            {
                source.Replace(
                    token.OriginalSource,
                    "sender");

                return(true);
            }

            if (obj is PLayoutBinderHost host)
            {
                targetVisuals.Add(host.LogicalParent);
            }

            if (obj is PSelector selector)
            {
                targetVisuals.Clear();
                targetVisuals.SafeAdd(selector.TargetVisual);
            }

            if (obj is PDataBinding binding)
            {
                if (trace.GetFrame(0).Source.GetType() == typeof(PSetter))
                {
                    source.Clear();
                    source.Append("DXDatastore");

                    return(true);
                }
            }

            if (obj is PTargetable targetable)
            {
                // 연결됨
                if (targetable.TargetBinder.Items.Count > 0)
                {
                    string        line  = source.ToString();
                    IBinderHost[] hosts = targetable.TargetBinder.Items
                                          .Select(item => item.Host)
                                          .ToArray();

                    isMultiline = true;
                    source.Clear();

                    for (int i = 0; i < hosts.Length; i++)
                    {
                        string  tempLine     = line;
                        PVisual targetVisual = null;

                        // 레이아웃에서 직접 연결
                        if (hosts[i] is PLayoutBinderHost targetLayoutHost)
                        {
                            targetVisual = targetLayoutHost.LogicalParent;
                        }

                        // 선택기로 가져옴
                        if (hosts[i] is PSelector targetSelector)
                        {
                            targetVisual = targetSelector.TargetVisual;
                        }

                        // Target을 해결하지 못한경우는 무조건 이벤트 sender
                        if (targetVisual == null)
                        {
                            tempLine = tempLine.Replace(token.OriginalSource, "sender");
                        }
                        else
                        {
                            // {Target} -> {Target:i}
                            tempLine = tempLine.Replace(token.OriginalSource, $"{{{token.Token}:{i}}}");
                            targetVisuals.Add(targetVisual);
                        }

                        if (i > 0)
                        {
                            source.AppendLine();
                        }

                        source.Append(tempLine);
                    }
                }
            }

            for (int i = 0; i < targetVisuals.Count; i++)
            {
                if (this.NameContainer.ContainsValue(targetVisuals[i]))
                {
                    string name        = this.NameContainer[targetVisuals[i]].Trim('_');
                    string tokenSource = token.OriginalSource;

                    if (isMultiline)
                    {
                        tokenSource = $"{{{token.Token}:{i}}}";
                    }

                    source.Replace(
                        tokenSource,
                        name);
                }
            }

            if (targetVisuals.Count > 0)
            {
                return(true);
            }

            return(false);
        }
Esempio n. 4
0
        private DXMappingResult buildImpl(BuildStackTrace trace, object obj, string source)
        {
            // trace capture
            trace.Capture(obj, source);

            var result        = new DXMappingResult();
            var sourceBuilder = new StringBuilder(source);

            // 이벤트 핸들러 연결 코드 및 콜백 이름 생성
            if (obj is PTrigger trigger && source.Contains("{EventName}"))
            {
                var eventBuilder = new StringBuilder();

                string eventName = this.MappingProvider.GetEventName(trigger);

                source = source.Replace("{EventName}", eventName);

                foreach (var item in trigger
                         .GetExpressions()
                         .Where(e => e.Direction == BindDirection.Input && e.Input.BindOption == BindOptions.Input))
                {
                    var targetHost = item.Output.Host as PLayoutBinderHost;

                    var hostResult = buildImpl(trace, targetHost, source);

                    eventBuilder.AppendLine(hostResult.Source);

                    foreach (DXToken errorToken in hostResult.Errors)
                    {
                        result.AddErrorToken(errorToken);
                    }

                    foreach (DXToken resolvedToken in hostResult.Resolved)
                    {
                        result.AddErrorToken(resolvedToken);
                    }
                }

                sourceBuilder = new StringBuilder(eventBuilder.ToString());
            }

            // 토큰 처리
            foreach (DXToken token in DXToken.Parse(sourceBuilder.ToString()))
            {
                if (!IsSupportToken(token))
                {
                    result.Errors.Add(token);
                    continue;
                }

                bool tokenResult = false;

                switch (token.Token)
                {
                case "Property":
                    tokenResult = this.BuildProperty(trace, result, token, obj, sourceBuilder);
                    break;

                case "Function":
                    tokenResult = this.BuildFunction(trace, result, token, obj, sourceBuilder);
                    break;

                case "Target":
                    tokenResult = this.BuildTarget(trace, result, token, obj, sourceBuilder);
                    break;

                case "Param":
                    tokenResult = this.BuildParam(trace, result, token, obj, sourceBuilder);
                    break;
                }

                if (tokenResult)
                {
                    result.AddResolvedToken(token);
                }
                else
                {
                    result.AddErrorToken(token);

                    if (token.IsSafe)
                    {
                        sourceBuilder.Replace(token.OriginalSource, "");
                    }
                }
            }

            result.Source = sourceBuilder.ToString();

            return(result);
        }
Esempio n. 5
0
        public DXMappingResult Build(object obj, string source)
        {
            var trace = new BuildStackTrace();

            return(buildImpl(trace, obj, source));
        }
Esempio n. 6
0
        private bool BuildFunction(BuildStackTrace trace, DXMappingResult result, DXToken token, object obj, StringBuilder source)
        {
            Type objType = obj.GetType();

            if (!token.HasParameter)
            {
                return(false);
            }

            // 클래스가 아닌경우
            if (!obj.GetType().IsClass)
            {
                return(false);
            }

            if (token.HasReturn)
            {
                // * 함수 정보에서 가져옴

                if (obj is PFunction pFunc)
                {
                    if (pFunc.Items.Find(BindOptions.Parameter).Count() != pFunc.ParameterInfos.Length)
                    {
                        return(false);
                    }

                    if (pFunc.FunctionInfo.RuntimeMethodInfo.HasAttribute <TAttribute>())
                    {
                        var tAttr   = pFunc.FunctionInfo.RuntimeMethodInfo.GetAttribute <TAttribute>();
                        var tResult = buildImpl(trace, pFunc, tAttr.MappingCode);

                        source.Replace(
                            token.OriginalSource,
                            $"({tResult.Source})");
                    }
                    else
                    {
                        List <string> lines = this.BuildBinderHost(trace, pFunc);

                        source.Replace(
                            token.OriginalSource,
                            this.MappingProvider.GetFunctionLine(pFunc, lines.ToArray()));
                    }

                    foreach (DXToken iToken in DXToken.Parse(source.ToString()))
                    {
                        result.AddErrorToken(iToken);
                    }
                }
            }
            else
            {
                // * 함수 호출 및 반환값으로 치환

                // 토큰 파라미터로 메서드 가져옴
                MethodInfo mi = objType.GetMethod(token.Parameters.FirstOrDefault());

                int depth = token.SubParameters.GetInt("depth");

                // 지원하지 않는 메서드
                if (!IsSupportMethod(mi))
                {
                    return(false);
                }
                if (mi == null || obj == null)
                {
                }
                // 메서드 호출
                string code = (string)mi.Invoke(obj, new object[] { depth });

                source.Replace(
                    token.OriginalSource,
                    code);

                return(true);
            }

            return(false);
        }
Esempio n. 7
0
        private bool BuildProperty(BuildStackTrace trace, DXMappingResult result, DXToken token, object obj, StringBuilder source)
        {
            try
            {
                Type objType = obj.GetType();

                if (!token.HasParameter)
                {
                    return(false);
                }

                // 클래스가 아닌경우
                if (!obj.GetType().IsClass)
                {
                    return(false);
                }

                // 인라인 파라미터
                bool inline = token.SubParameters.GetBool("inline");

                // 속성에서 실제값을 가져옴
                var propertySolve = SolvePropertyValue(obj, token.Parameters.FirstOrDefault());

                if (!propertySolve.Solved)
                {
                    return(false);
                }

                string valueLine = null;

                // 속성값이 바인더인 경우
                if (propertySolve.Result is PBinder binder)
                {
                    valueLine = this.BuildBinder(trace, result, binder);
                }
                else if (IsArrayType(propertySolve.Result?.GetType()))
                {
                    var sb   = new StringBuilder();
                    var list = propertySolve.Result as IList;

                    if (list.Count > 0)
                    {
                        foreach (object item in list)
                        {
                            if (sb.Length > 0)
                            {
                                sb.Append(", ");
                            }

                            if (item is PComponent)
                            {
                                var attr = item.GetAttribute <TAttribute>();

                                sb.Append(buildImpl(trace, item, attr.MappingCode).Source);
                            }
                            else
                            {
                                sb.Append(item);
                            }
                        }

                        valueLine = sb.ToString();
                    }
                }
                else if (propertySolve.Result is DependencyProperty prop)
                {
                    PropertyInfo targetPi = prop.OwnerType.GetProperty(prop.Name);

                    valueLine = this.MappingProvider.GetValueLine(targetPi, inline);
                }
                // 객체 참조인 경우
                else if (propertySolve.Result is Guid guid)
                {
                    foreach (var model in this.SharedConatiner.Values)
                    {
                        if (model is PObject pObj)
                        {
                            if (guid == pObj.Guid)
                            {
                                valueLine = this.MappingProvider.GetValueLine(this.SharedConatiner[pObj], inline);
                                break;
                            }
                        }
                    }
                }
                else
                {
                    valueLine = this.MappingProvider.GetValueLine(propertySolve.Result, inline);
                }

                if (propertySolve.Result == null &&
                    obj is PTargetable targetable &&
                    targetable.TargetType == typeof(PBucket))
                {
                    // A.B = C;
                    // A.B(~~, C);
                    if (targetable.TargetBinder.Items.Count > 0 &&
                        targetable.TargetBinder.Items[0].Host is PDataBinding)
                    {
                        var bucket = targetable.TargetBinder.Items[0].Host as PDataBinding;

                        source.Replace(" = ", $"(\"{bucket.DataPath}\", ");
                        source.Replace(";", ");");

                        valueLine = "Update";
                    }
                }

                if (valueLine != null)
                {
                    // source 토큰 치환
                    foreach (DXToken innerToken in DXToken.Parse(valueLine))
                    {
                        source.Replace(innerToken.OriginalSource, "");
                    }

                    source.Replace(
                        token.OriginalSource,
                        valueLine);
                }
            }
            catch (Exception e)
            {
            }

            return(true);
        }
Esempio n. 8
0
        private string BuildBinder(BuildStackTrace trace, DXMappingResult result, PBinder binder)
        {
            // 직접 입력 값
            if (binder.IsDirectValue)
            {
                object value = binder.DirectValue;

                if (value is string vStr)
                {
                    Match match = Regex.Match(vStr, "(?<=^\")(\\d+\\.\\d+|\\d+)(?=\"$)");

                    if (match.Success)
                    {
                        return(vStr);
                    }
                    else if (double.TryParse(vStr, out double v))
                    {
                        return(v.ToString());
                    }
                    else if (vStr == "\"\"")
                    {
                        return(vStr);
                    }
                }

                return(MappingProvider.GetValueLine(value, true));
            }

            // 연결된 파라미터가 없음
            if (binder.Items.Count == 0)
            {
                return(null);
            }

            // 연결된 파라미터의 부모 (컴포넌트)
            var    previousHost = binder.Items[0].Host as PBinderHost;
            string mappingCode  = previousHost.GetAttribute <TAttribute>().MappingCode;

            if (binder.HasAttribute <TAttribute>())
            {
                mappingCode = binder.GetAttribute <TAttribute>().MappingCode;
            }

            // 코드 매핑
            var r = buildImpl(trace, previousHost, mappingCode);

            string valueLine = r.Source;

            foreach (var token in r.Errors)
            {
                result.AddErrorToken(token);
            }

            foreach (var token in r.Resolved)
            {
                result.AddResolvedToken(token);
            }

            // 대입 값인 경우 대상 속성에 따라 캐스팅이 필요함
            if ((binder as PParameterBinder).Host is PSetter setter)
            {
                if (setter.ValueBinder.Equals(binder))
                {
                    Type valueType = previousHost.GetType();

                    if (previousHost is PFunction prevFunc)
                    {
                        valueType = prevFunc.FunctionInfo.ReturnType;
                    }

                    if (previousHost is PGetter prevGetter)
                    {
                        valueType = prevGetter.Property.PropertyType;
                    }

                    if (previousHost is PLayoutBinderHost prevLayout)
                    {
                        valueType = prevLayout.LogicalParent.GetType();
                    }

                    if (previousHost is PSelector prevSelector)
                    {
                        valueType = prevSelector.TargetVisual.GetType();
                    }

                    if (setter.Property == null && previousHost is PStructure structure)
                    {
                        if (structure.Fields.Count > 0)
                        {
                            var builder = new StringBuilder();
                            var attr    = typeof(PDataField).GetAttribute <TAttribute>();

                            PDataField[] fields = structure.Fields
                                                  .Where(f => f.ValueBinder.Items.Count > 0)
                                                  .OrderBy(f => f.ValueBinder.Items[0].Host is PFunction ? 1 : 0)
                                                  .ToArray();

                            for (int i = 0; i < fields.Length; i++)
                            {
                                if (fields[i].ValueBinder.Items.Count == 0)
                                {
                                    continue;
                                }

                                var fieldResult = buildImpl(trace, fields[i], attr.MappingCode);

                                if (builder.Length > 0)
                                {
                                    builder.Append(", ");
                                }

                                builder.Append(fieldResult.Source);
                            }

                            return(builder.ToString());
                        }

                        return("");
                    }

                    if (setter.Property.PropertyType != valueType ||
                        setter.Property.Name == "Source")
                    {
                        // on wpf
                        if (setter.Property.Name == "Source")
                        {
                            return(this.MappingProvider.Casting(typeof(ImageSource), valueLine));
                        }

                        // casting
                        return(this.MappingProvider.Casting(setter.Property.PropertyType, valueLine));
                    }
                }
            }

            return(valueLine);
        }