private string GenerateMethod(MethodInfo methodInfo)
        {
            var sb = new StringBuilder();

            var methodParameters = string.Join(",", methodInfo.Parameters.Select(p => p.Type + " " + p.Name));
            var methodParameterNames = string.Join(",", methodInfo.Parameters.Select(p => p.Name));
            var typesNotReturned = new[] {"void", "System.Threading.Tasks.Task"};
            var returnValue = typesNotReturned.All(t => t != methodInfo.ReturnTypeName);

            // Method declaration
            sb.AppendLine("public " + (methodInfo.IsAsync? "async ":"") + methodInfo.ReturnTypeName + " " + methodInfo.Name + "(" + methodParameters + ")");
            sb.AppendLine("{");

            if(returnValue)
            {
                var retType = methodInfo.IsAsync ? methodInfo.GetTaskRetunTypeName() : methodInfo.ReturnTypeName;
                sb.AppendLine("var ret = default("+ retType + ");");
            }

            // Try-catch
            if (DecoratorInfo.OnExceptionExist)
            {
                sb.AppendLine("try");
                sb.AppendLine("{");
            }

            // Init
            sb.AppendLine((methodInfo.IsAsync ? "await InitAsync" : "Init") + "(\""+ methodInfo.Name + "\", new object[] { " + methodParameterNames + " });");

            // OnEntry method
            if (DecoratorInfo.OnEntryExist)
            {
                sb.AppendLine("OnEntry();");
            }

            if (returnValue)
            {
                sb.Append("ret = ");
            }
            sb.AppendLine((methodInfo.IsAsync ? "await " : " ") + _decoratedComponent + "." + methodInfo.Name + "(" + methodParameterNames + ");");

            // OnExit method
            if (DecoratorInfo.OnExitExist)
            {
                sb.AppendLine("OnExit();");
            }

            // Try-catch
            if (DecoratorInfo.OnExceptionExist)
            {
                sb.AppendLine("}");
                sb.AppendLine("catch(System.Exception e)");
                sb.AppendLine("{");
                sb.AppendLine("OnException(e);");
                sb.AppendLine("}");

                // Finally
                if (DecoratorInfo.OnFinallyExist)
                {
                    sb.AppendLine("finally");
                    sb.AppendLine("{");
                    sb.AppendLine("OnFinally();");
                    sb.AppendLine("}");
                }
            }

            if (returnValue)
            {
                sb.AppendLine("return ret;");
            }

            sb.AppendLine("}");
            return sb.ToString();
        }
        public IReadOnlyCollection<ICodeClassDecoratorGenerator> GetDecorators()
        {
            var ret = new List<ICodeClassDecoratorGenerator>();

            foreach (var cls in _configuration.DecoratedClass)
            {
                // Init
                var codeClassGenerator = new CodeClassDecoratorGenerator();
                var decoratedClassInfo = new DecoratorInfo()
                {
                    DecoratedClassTypeFullName = cls.SourceClassName,
                    DecoratorClassTypeShortName = cls.TargetClassName
                };
                codeClassGenerator.DecoratorInfo = decoratedClassInfo;

                // Get decorated class
                var decoratedClass = _syntaxWalker.GetClassByFullName(cls.SourceClassName);
                if(decoratedClass==null)
                {
                    codeClassGenerator.AnalysisError = string.Format("Decorated class {0} not found!", cls.SourceClassName);
                    ret.Add(codeClassGenerator);
                    continue;
                }

                decoratedClassInfo.DecoratedClassTypeShortName = decoratedClass.Name;
                decoratedClassInfo.Namespace = decoratedClass.ContainingNamespace.ToString();
                decoratedClassInfo.DecoratorClassTypeFullName = decoratedClassInfo.Namespace + "." + cls.TargetClassName;
                //decoratedClassInfo.RequiredNamespaces = _syntaxWalker.GetUsings(decoratedClass);

                // Get decorator class
                var decoratorClass = _syntaxWalker.GetClassByFullName(decoratedClassInfo.DecoratorClassTypeFullName);
                if (decoratorClass == null)
                {
                    codeClassGenerator.AnalysisError = string.Format("Partial decorator class {0} not found!", decoratedClassInfo.DecoratorClassTypeFullName);
                    ret.Add(codeClassGenerator);
                    continue;
                }

                // Get methods for decorating
                var methods = decoratedClass.GetMembers()
                    .Where(m => m.Kind == SymbolKind.Method && m.DeclaredAccessibility == Accessibility.Public && m.MetadataName != ".ctor")
                    .Select(m=> m as IMethodSymbol)
                    .Where(m => m.AssociatedSymbol == null || m.AssociatedSymbol.Kind != SymbolKind.Property)
                    .ToList();

                // Get methods from decorator
                var decoratorImplementedMethods = decoratorClass.GetMembers()
                    .Where(m => m.Kind == SymbolKind.Method)
                    .Select(m => m as IMethodSymbol)
                    .ToList();

                foreach (var m in methods)
                {
                    // Skip already decorated methods
                    if(decoratorImplementedMethods.Any(dm => dm.Name == m.Name)) continue;

                    var method = new MethodInfo()
                    {
                        Name = m.Name,
                        ReturnTypeName = m.ReturnType.ToString(),
                        IsAsync = m.IsAsync,
                        ReturnTypeIsNullble = !m.ReturnType.IsValueType,
                        Parameters = m.Parameters.Select(p => new ParameterInfo()
                        {
                            Name = p.Name,
                            Type = p.Type.ToString()
                        }).ToList(),
                    };

                    decoratedClassInfo.MethodInfos.Add(method);
                }

                // Set flags for include decorator methods
                decoratedClassInfo.OnEntryExist = decoratorImplementedMethods.FirstOrDefault(m => m.Name == _entryMethodName) != null;
                decoratedClassInfo.OnExitExist = decoratorImplementedMethods.FirstOrDefault(m => m.Name == _exitMethodName) != null;
                decoratedClassInfo.OnExceptionExist = decoratorImplementedMethods.FirstOrDefault(m => m.Name == _exceptionMethodName) != null;
                decoratedClassInfo.OnFinallyExist = decoratorImplementedMethods.FirstOrDefault(m => m.Name == _finallyMethodName) != null;

                ret.Add(codeClassGenerator);
            }

            return ret;
        }