Permalink
Browse files

Added fluent regex, improved invoke chained to use indexers. InvokeSe…

…tIndex

returns value, Marked MVVM framework as beta.
  • Loading branch information...
1 parent 494cb48 commit b782dde3c00ab7e83223f88422389ffadee23830 jayt committed Aug 2, 2012
Showing with 304 additions and 29 deletions.
  1. +4 −0 .nuget/packages.config
  2. +2 −2 ImpromptuInterface.FSharp.Silverlight/ImpromptuInterface.FSharp (Silverlight).fsproj
  3. +2 −2 ImpromptuInterface.MVVM/Properties/AssemblyInfo.cs
  4. +6 −0 ImpromptuInterface.Silverlight/ImpromptuInterface (Silverlight).csproj
  5. +6 −0 ImpromptuInterface.Silverlight5/ImpromptuInterface (Silverlight5).csproj
  6. +1 −0 ImpromptuInterface.sln
  7. +2 −0 ImpromptuInterface/ImpromptuInterface.csproj
  8. +2 −2 ImpromptuInterface/Properties/AssemblyInfo.cs
  9. +65 −0 ImpromptuInterface/src/Dynamic/FluentRegex.cs
  10. +88 −0 ImpromptuInterface/src/Dynamic/ImpromptuMatch.cs
  11. +69 −10 ImpromptuInterface/src/Impromptu.cs
  12. +2 −2 ImpromptuInterface/src/Optimization/InvokeHelper-Regular.cs
  13. +1 −1 NuGetBuild/Core/ImpromptuInterface.MetaData.xml
  14. +1 −1 NuGetBuild/Core/ImpromptuInterface.Symbol.nuspec
  15. +1 −1 NuGetBuild/Core/ImpromptuInterface.nuspec
  16. +1 −1 NuGetBuild/MVVM/ImpromptuInterface.MVVM.MetaData.xml
  17. +1 −1 NuGetBuild/MVVM/ImpromptuInterface.MVVM.Symbol.nuspec
  18. +1 −1 NuGetBuild/MVVM/ImpromptuInterface.MVVM.nuspec
  19. +4 −1 Tests/UnitTestImpromptu.FSharp.Silverlight/UnitTestImpromptu.FSharp.Silverlight.fsproj
  20. +1 −1 Tests/UnitTestImpromptu.FSharp.Silverlight/packages.config
  21. +4 −1 Tests/UnitTestImpromptuInterface.FSharp/UnitTestImpromptuInterface.FSharp.fsproj
  22. +2 −2 Tests/UnitTestImpromptuInterface.FSharp/packages.config
  23. +38 −0 Tests/UnitTestImpromptuInterface/SingleMethodInvoke.cs
View
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NuGet.CommandLine" version="2.0.0" />
+</packages>
@@ -7,7 +7,7 @@
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{c6f699c3-c2c7-4393-b8c2-b5c234ed23d7}</ProjectGuid>
<OutputType>Library</OutputType>
- <AssemblyName>ImpromptuInterface.FSharp.Silverlight</AssemblyName>
+ <AssemblyName>ImpromptuInterface.FSharp</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
<FileAlignment>512</FileAlignment>
@@ -37,7 +37,7 @@
<DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>3</WarningLevel>
- <DocumentationFile>bin\Release\ImpromptuInterface.FSharp.Silverlight.XML</DocumentationFile>
+ <DocumentationFile>bin\Release\ImpromptuInterface.FSharp.XML</DocumentationFile>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
@@ -42,7 +42,7 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
#if SILVERLIGHT
-[assembly: AssemblyVersion("4.0.0.0")]
+[assembly: AssemblyVersion("4.0.1.1")]
#else
-[assembly: AssemblyVersion("4.0.0.*")]
+[assembly: AssemblyVersion("4.0.1.*")]
#endif
@@ -100,6 +100,9 @@
<Compile Include="..\ImpromptuInterface\src\Dynamic\CacheableInvocation.cs">
<Link>src\Dynamic\CacheableInvocation.cs</Link>
</Compile>
+ <Compile Include="..\ImpromptuInterface\src\Dynamic\FluentRegex.cs">
+ <Link>src\Dynamic\FluentRegex.cs</Link>
+ </Compile>
<Compile Include="..\ImpromptuInterface\src\Dynamic\IActLike.cs">
<Link>src\Dynamic\IActLike.cs</Link>
</Compile>
@@ -139,6 +142,9 @@
<Compile Include="..\ImpromptuInterface\src\Dynamic\ImpromptuList.cs">
<Link>src\Dynamic\ImpromptuList.cs</Link>
</Compile>
+ <Compile Include="..\ImpromptuInterface\src\Dynamic\ImpromptuMatch.cs">
+ <Link>src\Dynamic\ImpromptuMatch.cs</Link>
+ </Compile>
<Compile Include="..\ImpromptuInterface\src\Dynamic\ImpromptuObject.cs">
<Link>src\Dynamic\ImpromptuObject.cs</Link>
</Compile>
@@ -83,6 +83,9 @@
<Compile Include="..\ImpromptuInterface\src\Dynamic\CacheableInvocation.cs">
<Link>src\Dynamic\CacheableInvocation.cs</Link>
</Compile>
+ <Compile Include="..\ImpromptuInterface\src\Dynamic\FluentRegex.cs">
+ <Link>src\Dynamic\FluentRegex.cs</Link>
+ </Compile>
<Compile Include="..\ImpromptuInterface\src\Dynamic\IActLike.cs">
<Link>src\Dynamic\IActLike.cs</Link>
</Compile>
@@ -122,6 +125,9 @@
<Compile Include="..\ImpromptuInterface\src\Dynamic\ImpromptuList.cs">
<Link>src\Dynamic\ImpromptuList.cs</Link>
</Compile>
+ <Compile Include="..\ImpromptuInterface\src\Dynamic\ImpromptuMatch.cs">
+ <Link>src\Dynamic\ImpromptuMatch.cs</Link>
+ </Compile>
<Compile Include="..\ImpromptuInterface\src\Dynamic\ImpromptuObject.cs">
<Link>src\Dynamic\ImpromptuObject.cs</Link>
</Compile>
View
@@ -57,6 +57,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{0D3016
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.exe = .nuget\NuGet.exe
.nuget\NuGet.targets = .nuget\NuGet.targets
+ .nuget\packages.config = .nuget\packages.config
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImpromptuInterface (Silverlight5)", "ImpromptuInterface.Silverlight5\ImpromptuInterface (Silverlight5).csproj", "{EC1B3513-CB1E-4796-899F-125FC05B2F41}"
@@ -109,6 +109,8 @@
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="src\ActLikeCaster.cs" />
+ <Compile Include="src\Dynamic\ImpromptuMatch.cs" />
+ <Compile Include="src\Dynamic\FluentRegex.cs" />
<Compile Include="src\Dynamic\Mimic.cs" />
<Compile Include="src\Dynamic\Builder.cs" />
<Compile Include="src\Dynamic\CacheableInvocation.cs" />
@@ -59,10 +59,10 @@
#if SILVERLIGHT
-[assembly: AssemblyVersion("6.0.0.0")]
+[assembly: AssemblyVersion("6.0.1.0")]
#else
-[assembly: AssemblyVersion("6.0.0.*")]
+[assembly: AssemblyVersion("6.0.1.*")]
#endif
@@ -0,0 +1,65 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace ImpromptuInterface.Dynamic
+{
+ /// <summary>
+ /// Extension Methods for fluent Regex
+ /// </summary>
+ public static class FluentRegex
+ {
+
+ public static IEnumerable<dynamic> FluentFilter(this IEnumerable<string> list, Regex regex)
+ {
+ return list.Select(it => regex.Match(it)).Where(it => it.Success).Select(it => new ImpromptuMatch(it, regex)).Cast<dynamic>();
+ }
+
+ public static IEnumerable<dynamic> Matches(string inputString, Regex regex)
+ {
+ var tMatches = regex.Matches(inputString);
+
+ return tMatches.Cast<Match>().Where(it => it.Success).Select(it => new ImpromptuMatch(it, regex)).Cast<dynamic>();
+ }
+
+ public static dynamic Match(string inputString, Regex regex)
+ {
+ var tMatch = regex.Match(inputString);
+ return tMatch.Success ? new ImpromptuMatch(tMatch, regex) : null;
+ }
+
+ public static dynamic FluentMatch(this Regex regex, string inputString)
+ {
+ var tMatch = regex.Match(inputString);
+ return tMatch.Success ? new ImpromptuMatch(tMatch,regex) : null;
+ }
+
+ public static IEnumerable<dynamic> FluentMatches(this Regex regex, string inputString)
+ {
+ return Matches(inputString, regex);
+ }
+
+ public static T Match<T>(string inputString, Regex regex) where T : class
+ {
+ var tMatch = Match(inputString, regex);
+ return tMatch == null ? null : Impromptu.DynamicActLike(tMatch, typeof(T));
+ }
+
+ public static T FluentMatch<T>(this Regex regex, string inputString) where T : class
+ {
+ var tMatch = regex.Match(inputString);
+ return tMatch.Success ? new ImpromptuMatch(tMatch, regex).ActLike<T>() : null;
+ }
+
+ public static IEnumerable<T> FluentMatches<T>(this Regex regex,string inputString) where T : class
+ {
+ return Matches(inputString,regex).AllActLike<T>();
+ }
+
+ public static IEnumerable<T> FluentFilter<T>(this IEnumerable<string> list, Regex regex) where T : class
+ {
+ return FluentFilter(list, regex).AllActLike<T>();
+ }
+
+ }
+}
@@ -0,0 +1,88 @@
+using System;
+using System.Dynamic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+namespace ImpromptuInterface.Dynamic
+{
+
+ public interface IFluentMatch
+ {
+ string Value { get;}
+ }
+
+ public class ImpromptuMatch : ImpromptuObject, IFluentMatch
+ {
+ private readonly Match _match;
+ private readonly Regex _regex;
+ public ImpromptuMatch(Match match, Regex regex =null)
+ {
+ _match = match;
+ _regex = regex;
+ }
+
+ public override IEnumerable<string> GetDynamicMemberNames()
+ {
+ if (_regex == null)
+ return Enumerable.Empty<string>();
+ return _regex.GetGroupNames();
+ }
+
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ var tGroup = _match.Groups[binder.Name];
+ Type outType;
+ if (!TryTypeForName(binder.Name, out outType))
+ outType = typeof (string);
+
+ if (!tGroup.Success)
+ {
+ result = null;
+ if (outType.IsValueType)
+ result = Impromptu.InvokeConstructor(outType);
+ return true;
+ }
+
+ result = Impromptu.CoerceConvert(tGroup.Value, outType);
+ return true;
+ }
+
+ public string this[int value]
+ {
+ get
+ {
+ var tGroup = _match.Groups[value];
+
+ if (!tGroup.Success)
+ {
+ return null;
+ }
+ return tGroup.Value;
+ }
+ }
+
+ public string this[string value]
+ {
+ get
+ {
+ var tGroup = _match.Groups[value];
+
+ if (!tGroup.Success)
+ {
+ return null;
+ }
+ return tGroup.Value;
+ }
+ }
+
+ string IFluentMatch.Value
+ {
+ get { return _match.Value; }
+ }
+
+ public override string ToString()
+ {
+ return _match.ToString();
+ }
+ }
+}
@@ -26,7 +26,7 @@
using ImpromptuInterface.InvokeExt;
using ImpromptuInterface.Optimization;
using Microsoft.CSharp.RuntimeBinder;
-
+using System.Text.RegularExpressions;
namespace ImpromptuInterface
{
using System;
@@ -306,7 +306,7 @@ public static dynamic InvokeGetIndex(object target, params object[] indexes)
/// </summary>
/// <param name="target">The target.</param>
/// <param name="indexesThenValue">The indexes then value.</param>
- public static void InvokeSetIndex(object target, params object[] indexesThenValue)
+ public static object InvokeSetIndex(object target, params object[] indexesThenValue)
{
string[] tArgNames;
Type tContext;
@@ -315,7 +315,7 @@ public static void InvokeSetIndex(object target, params object[] indexesThenValu
indexesThenValue = Util.GetArgsAndNames(indexesThenValue, out tArgNames);
CallSite tCallSite = null;
- InvokeHelper.InvokeSetIndexCallSite(target, indexesThenValue, tArgNames, tContext, tStaticContext,
+ return InvokeHelper.InvokeSetIndexCallSite(target, indexesThenValue, tArgNames, tContext, tStaticContext,
ref tCallSite);
}
@@ -417,13 +417,47 @@ public static object InvokeSet(object target, string name, object value)
/// <param name="value">The value.</param>
public static object InvokeSetChain(object target, string propertyChain, object value)
{
- var tProperties = propertyChain.Split('.');
- var tGetProperties = tProperties.Take(tProperties.Length - 1);
+ var tProperties = _chainRegex.FluentMatches(propertyChain).ToList();
+ var tGetProperties = tProperties.Take(tProperties.Count - 1);
+
+
+ var tTarget = target;
+ foreach (var tProperty in tGetProperties)
+ {
+ var tGetter = tProperty.Getter;
+ var tIntIndexer = tProperty.IntIndexer;
+ var tStringIndexer = tProperty.StringIndexer;
+
+ if (tGetter != null)
+ tTarget = InvokeGet(tTarget, tGetter);
+ else if (tIntIndexer != null)
+ tTarget = InvokeGetIndex(tTarget, Impromptu.CoerceConvert(tIntIndexer, typeof(int)));
+ else if (tStringIndexer != null)
+ tTarget = InvokeGetIndex(tTarget, tStringIndexer);
+ else
+ {
+ throw new Exception(string.Format("Could Not Parse :'{0}'", propertyChain));
+ }
+ }
+
var tSetProperty = tProperties.Last();
- var tSetTarget = tGetProperties.Aggregate(target, InvokeGet);
- return InvokeSet(tSetTarget, tSetProperty, value);
+
+ var tSetGetter = tSetProperty.Getter;
+ var tSetIntIndexer = tSetProperty.IntIndexer;
+ var tSetStringIndexer = tSetProperty.StringIndexer;
+
+ if (tSetGetter != null)
+ return InvokeSet(tTarget, tSetGetter, value);
+ if (tSetIntIndexer != null)
+ return InvokeSetIndex(tTarget, Impromptu.CoerceConvert(tSetIntIndexer, typeof(int)), value);
+ if (tSetStringIndexer != null)
+ return InvokeSetIndex(tTarget, tSetStringIndexer, value);
+
+ throw new Exception(string.Format("Could Not Parse :'{0}'", propertyChain));
}
+
+
@@ -489,7 +523,14 @@ public static dynamic InvokeGet(object target, string name)
CallSite tSite = null;
return InvokeHelper.InvokeGetCallSite(target, name, tContext, tStaticContext, ref tSite);
}
-
+#if SILVERLIGHT
+ private static readonly Regex _chainRegex
+ = new Regex(@"((\.?(?<Getter>\w+))|(\[(?<IntIndexer>\d+)\])|(\['(?<StringIndexer>\w+)'\]))");
+#else
+ private static readonly Regex _chainRegex
+ = new Regex(@"((\.?(?<Getter>\w+))|(\[(?<IntIndexer>\d+)\])|(\['(?<StringIndexer>\w+)'\]))",RegexOptions.Compiled);
+#endif
+
/// <summary>
/// Invokes the getter property chain.
/// </summary>
@@ -498,8 +539,26 @@ public static dynamic InvokeGet(object target, string name)
/// <returns></returns>
public static dynamic InvokeGetChain(object target, string propertyChain)
{
- var tProperties = propertyChain.Split('.');
- return tProperties.Aggregate(target, InvokeGet);
+ var tProperties = _chainRegex.FluentMatches(propertyChain);
+ var tTarget = target;
+ foreach (var tProperty in tProperties)
+ {
+ var tGetter = tProperty.Getter;
+ var tIntIndexer = tProperty.IntIndexer;
+ var tStringIndexer = tProperty.StringIndexer;
+
+ if (tGetter != null)
+ tTarget = InvokeGet(tTarget, tGetter);
+ else if (tIntIndexer != null)
+ tTarget = InvokeGetIndex(tTarget, Impromptu.CoerceConvert(tIntIndexer,typeof(int)));
+ else if (tStringIndexer != null)
+ tTarget = InvokeGetIndex(tTarget, tStringIndexer);
+ else
+ {
+ throw new Exception(string.Format("Could Not Parse :'{0}'", propertyChain));
+ }
+ }
+ return tTarget;
}
/// <summary>
Oops, something went wrong.

0 comments on commit b782dde

Please sign in to comment.