コード例 #1
0
        private bool BuildFunction(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);
                    }

                    List <string> lines = this.BuildBinderHost(pFunc);

                    source.Replace(
                        token.OriginalSource,
                        this.MappingProvider.GetFunctionLine(pFunc, lines.ToArray()));
                }
            }
            else
            {
                // * 함수 호출 및 반환값으로 치환

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

                // 지원하지 않는 메서드
                if (!IsSupportMethod(mi))
                {
                    return(false);
                }

                // 메서드 호출
                string code = (string)mi.Invoke(obj, null);

                source.Replace(
                    token.OriginalSource,
                    code);

                return(true);
            }

            return(false);
        }
コード例 #2
0
        private bool BuildProperty(DXToken token, object obj, StringBuilder source)
        {
            Type objType = obj.GetType();

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

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

            PropertyInfo pi = objType.GetProperty(token.Parameter);

            if (pi == null)
            {
                return(false);
            }

            // 속성에서 실제값을 가져옴
            object value     = pi.GetValue(obj);
            string valueLine = null;

            // 속성값이 바인더인 경우
            if (value is PBinder binder)
            {
                valueLine = this.BuildBinder(binder);
            }
            else if (value is DependencyProperty prop)
            {
                PropertyInfo targetPi = prop.OwnerType.GetProperty(prop.Name);

                valueLine = this.MappingProvider.GetValueLine(targetPi);
            }
            else
            {
                valueLine = this.MappingProvider.GetValueLine(value);
            }

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

                source.Replace(
                    token.OriginalSource,
                    valueLine);
            }

            return(true);
        }
コード例 #3
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);
        }
コード例 #4
0
 public static bool IsSupportToken(DXToken token)
 {
     return(SupportTokenHeaders.Contains(token.Token));
 }
コード例 #5
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);
        }
コード例 #6
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);
        }
コード例 #7
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);
        }
コード例 #8
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);
        }
コード例 #9
0
        private bool BuildTarget(DXToken token, object obj, StringBuilder source)
        {
            PVisual targetVisual = null;

            if (obj is PLayoutBinderHost host)
            {
                targetVisual = host.LogicalParent;
            }

            if (obj is PSelector selector)
            {
                targetVisual = selector.TargetVisual;
            }

            if (obj is PTargetable targetable)
            {
                // 연결됨
                if (targetable.TargetBinder.Items.Count > 0)
                {
                    IBinderHost targetHost = targetable.TargetBinder.Items[0].Host;

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

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

                    // Target을 해결하지 못한경우는 무조건 이벤트 sender
                    if (targetVisual == null)
                    {
                        source.Replace(token.OriginalSource, "sender");

                        return(true);
                    }
                }
            }

            if (this.NameContainer.ContainsValue(targetVisual))
            {
                string name = this.NameContainer[targetVisual].Trim('_');

                source.Replace(
                    token.OriginalSource,
                    name);

                return(true);
            }

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

                return(true);
            }

            return(false);
        }
コード例 #10
0
 public void AddErrorToken(DXToken token)
 {
     this.Resolved.SafeRemove(token);
     this.Errors.SafeAdd(token);
 }