From da0b54f1aaa6cb4827122914520a80a0750f7a62 Mon Sep 17 00:00:00 2001 From: AdmiringWorm Date: Tue, 21 Jul 2020 15:01:25 +0200 Subject: [PATCH] (GH-17) Added simple class for wrapping other classes --- .../Content/loader/AddinData.cake | 35 ++++++-- .../Content/loader/ClassWrapper.cake | 89 +++++++++++++++++++ Cake.Issues.Recipe/Content/loader/loader.cake | 3 +- .../reporters/GenericReporterData.cake | 6 +- 4 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 Cake.Issues.Recipe/Content/loader/ClassWrapper.cake diff --git a/Cake.Issues.Recipe/Content/loader/AddinData.cake b/Cake.Issues.Recipe/Content/loader/AddinData.cake index 3122b86d..f1b8661b 100644 --- a/Cake.Issues.Recipe/Content/loader/AddinData.cake +++ b/Cake.Issues.Recipe/Content/loader/AddinData.cake @@ -16,7 +16,7 @@ public class AddinData public IList _definedClasses = new List(); private IList _definedMethods = new List(); - public object CreateClass(string classTypeString, params object[] parameters) + public ClassWrapper CreateClass(string classTypeString, params object[] parameters) { var possibleClass = _definedClasses.FirstOrDefault(c => string.Compare(c.Name, classTypeString, StringComparison.OrdinalIgnoreCase) == 0); @@ -28,7 +28,7 @@ public class AddinData return CreateClass(possibleClass, parameters); } - public object CreateClass(TypeInfo classType, params object[] parameters) + public ClassWrapper CreateClass(TypeInfo classType, params object[] parameters) { parameters = parameters ?? new object[0]; var constructors = classType.DeclaredConstructors.Where(c => c.IsPublic && !c.IsStatic && c.GetParameters().Length == parameters.Length); @@ -51,10 +51,24 @@ public class AddinData throw new NullReferenceException("No valid constructor was found!"); } - return constructor.Invoke(parameters ?? new object[0]); + var result = constructor.Invoke(parameters ?? new object[0]); + + return new ClassWrapper(result, this); + } + + public TType CallStaticMethod(string methodName, params object[] parameters) + { + var result = CallStaticMethod(methodName, parameters); + + if (result.GetType().IsClass) + { + return (TType)result.ToActual(); + } + + return (TType)result; } - public object CallStaticMethod(string methodName, params object[] parameters) + public dynamic CallStaticMethod(string methodName, params object[] parameters) { parameters = TransformParameters(parameters); @@ -78,7 +92,14 @@ public class AddinData throw new NullReferenceException($"No method with the name '{methodName}' was found!"); } - return method.Invoke(null, parameters); + var result = method.Invoke(null, parameters); + + if (result.GetType().IsClass) + { + return new ClassWrapper(result, this); + } + + return result; } public object[] TransformParameters(params object[] parameters) @@ -112,6 +133,10 @@ public class AddinData } } } + else if (parameter is ClassWrapper wrapper) + { + value = wrapper.ToActual(); + } newParameters.Add(value); } diff --git a/Cake.Issues.Recipe/Content/loader/ClassWrapper.cake b/Cake.Issues.Recipe/Content/loader/ClassWrapper.cake new file mode 100644 index 00000000..417a1dc9 --- /dev/null +++ b/Cake.Issues.Recipe/Content/loader/ClassWrapper.cake @@ -0,0 +1,89 @@ +using System.Reflection; + +public sealed class ClassWrapper +{ + private readonly Type _classType; + private readonly object _concreteClass; + private readonly AddinData _addinData; + + public ClassWrapper(object concreteClass, AddinData addinData) + { + var classType = concreteClass.GetType(); + + if (!classType.IsClass) + { + throw new Exception($"The class {classType.Name} is not a class type!"); + } + + _concreteClass = concreteClass; + _addinData = addinData; + _classType = classType; + } + + public object GetPropertyValue(string propertyName) + { + var property = _classType.GetProperty(propertyName, BindingFlags.GetProperty | BindingFlags.Public); + + return property.GetValue(_concreteClass); + } + + public void SetPropertyValue(string propertyName, object value) + { + var property = _classType.GetProperty(propertyName, BindingFlags.SetProperty | BindingFlags.Public); + value = _addinData.TransformParameters(value).First(); + if (property.PropertyType.IsEnum && !value.GetType().IsEnum) + { + value = Enum.Parse(property.PropertyType, value.ToString()); + } + + property.SetValue(_concreteClass, value); + } + + public dynamic CallExtensionMethod(string methodName, params object[] parameters) + { + var newParameters = new List(); + newParameters.Add(_concreteClass); + newParameters.AddRange(_addinData.TransformParameters(parameters)); + + return _addinData.CallStaticMethod(methodName, newParameters.ToArray()); + } + + public dynamic CallMethod(string methodName, params object[] parameters) + { + parameters = _addinData.TransformParameters(parameters); + + var methods = _classType.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(m => string.Compare(m.Name, methodName, StringComparison.OrdinalIgnoreCase) == 0); + MethodInfo method = null; + + foreach (var m in methods.Where(m => m.GetParameters().Length == parameters.Length)) + { + var methodParams = m.GetParameters(); + bool useMethod = AddinData.ParametersMatch(methodParams, parameters); + + if (useMethod) + { + method = m; + break; + } + } + + if (method is null) + { + throw new NullReferenceException($"No method with the name '{methodName}' was found in the class '{_classType.Name}'"); + } + + var result = method.Invoke(_concreteClass, parameters); + + if (result.GetType().IsClass) + { + return new ClassWrapper(result, _addinData); + } + + return result; + } + + public object ToActual() + { + return _concreteClass; + } +} \ No newline at end of file diff --git a/Cake.Issues.Recipe/Content/loader/loader.cake b/Cake.Issues.Recipe/Content/loader/loader.cake index 71fc854d..5b996e74 100644 --- a/Cake.Issues.Recipe/Content/loader/loader.cake +++ b/Cake.Issues.Recipe/Content/loader/loader.cake @@ -1 +1,2 @@ -#load ./AddinData.cake \ No newline at end of file +#load ./AddinData.cake +#load ./ClassWrapper.cake \ No newline at end of file diff --git a/Cake.Issues.Recipe/Content/reporters/GenericReporterData.cake b/Cake.Issues.Recipe/Content/reporters/GenericReporterData.cake index 01ffa09a..8e5843ca 100644 --- a/Cake.Issues.Recipe/Content/reporters/GenericReporterData.cake +++ b/Cake.Issues.Recipe/Content/reporters/GenericReporterData.cake @@ -20,9 +20,9 @@ public class GenericReporterData : AddinData var settings = reporter.CallStaticMethod("FromEmbeddedTemplate", "HtmlDxDataGrid"); var theme = "DevExtremeTheme.MaterialBlueLight"; // Should be changed to be set on IssuesParametersReporting settings class. - reporter.CallStaticMethod("WithOption", settings, "HtmlDxDataGridOption.Theme", theme); + settings.CallExtensionMethod("WithOption", "HtmlDxDataGridOption.Theme", theme); - var issueFormat = (IIssueReportFormat)reporter.CallStaticMethod("GenericIssueReportFormat", context, settings); + var issueFormat = reporter.CallStaticMethod("GenericIssueReportFormat", context, settings); return issueFormat; } @@ -31,7 +31,7 @@ public class GenericReporterData : AddinData { var reporter = GetReporter(context); - var issueFormat = (IIssueReportFormat)reporter.CallStaticMethod("GenericIssueReportFormatFromFilePath", context, reportPath); + var issueFormat = reporter.CallStaticMethod("GenericIssueReportFormatFromFilePath", context, reportPath); return issueFormat; }