Browse Source

Add IQToolkit v0.16

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5011 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
eb4db62cd1
  1. BIN
      src/Libraries/IQToolkit/IQToolkit.dll
  2. 64
      src/Libraries/IQToolkit/IQToolkit/IQToolkit.csproj
  3. 20
      src/Libraries/IQToolkit/IQToolkit/IQToolkit.sln
  4. 175
      src/Libraries/IQToolkit/IQToolkit/PartialEvaluator.cs
  5. 36
      src/Libraries/IQToolkit/IQToolkit/Properties/AssemblyInfo.cs
  6. 114
      src/Libraries/IQToolkit/IQToolkit/Query.cs
  7. 54
      src/Libraries/IQToolkit/IQToolkit/QueryProvider.cs
  8. 41
      src/Libraries/IQToolkit/IQToolkit/ReflectionExtensions.cs
  9. 150
      src/Libraries/IQToolkit/IQToolkit/TypeHelper.cs
  10. 31
      src/Libraries/IQToolkit/license.txt
  11. 2
      src/Libraries/IQToolkit/readme.txt

BIN
src/Libraries/IQToolkit/IQToolkit.dll

Binary file not shown.

64
src/Libraries/IQToolkit/IQToolkit/IQToolkit.csproj

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0DA62A7C-3B40-456F-A4B2-B3E19ED4080E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>IQToolkit</RootNamespace>
<AssemblyName>IQToolkit</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StartupObject>
</StartupObject>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Runtime.Serialization">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Query.cs" />
<Compile Include="ReflectionExtensions.cs" />
<Compile Include="PartialEvaluator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="QueryProvider.cs" />
<Compile Include="TypeHelper.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

20
src/Libraries/IQToolkit/IQToolkit/IQToolkit.sln

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 10
# SharpDevelop 4.0.0.4995
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IQToolkit", "IQToolkit.csproj", "{0DA62A7C-3B40-456F-A4B2-B3E19ED4080E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0DA62A7C-3B40-456F-A4B2-B3E19ED4080E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DA62A7C-3B40-456F-A4B2-B3E19ED4080E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DA62A7C-3B40-456F-A4B2-B3E19ED4080E}.Release|Any CPU.Build.0 = Release|Any CPU
{0DA62A7C-3B40-456F-A4B2-B3E19ED4080E}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
EndGlobal

175
src/Libraries/IQToolkit/IQToolkit/PartialEvaluator.cs

@ -0,0 +1,175 @@ @@ -0,0 +1,175 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace IQToolkit
{
/// <summary>
/// Rewrites an expression tree so that locally isolatable sub-expressions are evaluated and converted into ConstantExpression nodes.
/// </summary>
public static class PartialEvaluator
{
/// <summary>
/// Performs evaluation & replacement of independent sub-trees
/// </summary>
/// <param name="expression">The root of the expression tree.</param>
/// <param name="fnCanBeEvaluated">A function that decides whether a given expression node can be part of the local function.</param>
/// <returns>A new tree with sub-trees evaluated and replaced.</returns>
public static Expression Eval(Expression expression, Func<Expression, bool> fnCanBeEvaluated)
{
return SubtreeEvaluator.Eval(Nominator.Nominate(fnCanBeEvaluated, expression), expression);
}
/// <summary>
/// Performs evaluation & replacement of independent sub-trees
/// </summary>
/// <param name="expression">The root of the expression tree.</param>
/// <returns>A new tree with sub-trees evaluated and replaced.</returns>
public static Expression Eval(Expression expression)
{
return Eval(expression, PartialEvaluator.CanBeEvaluatedLocally);
}
private static bool CanBeEvaluatedLocally(Expression expression)
{
return expression.NodeType != ExpressionType.Parameter;
}
/// <summary>
/// Evaluates & replaces sub-trees when first candidate is reached (top-down)
/// </summary>
class SubtreeEvaluator : ExpressionVisitor
{
HashSet<Expression> candidates;
private SubtreeEvaluator(HashSet<Expression> candidates)
{
this.candidates = candidates;
}
internal static Expression Eval(HashSet<Expression> candidates, Expression exp)
{
return new SubtreeEvaluator(candidates).Visit(exp);
}
public override Expression Visit(Expression exp)
{
if (exp == null)
{
return null;
}
if (this.candidates.Contains(exp))
{
return this.Evaluate(exp);
}
return base.Visit(exp);
}
private Expression Evaluate(Expression e)
{
Type type = e.Type;
if (e.NodeType == ExpressionType.Convert)
{
// check for unnecessary convert & strip them
var u = (UnaryExpression)e;
if (TypeHelper.GetNonNullableType(u.Operand.Type) == TypeHelper.GetNonNullableType(type))
{
e = ((UnaryExpression)e).Operand;
}
}
if (e.NodeType == ExpressionType.Constant)
{
// in case we actually threw out a nullable conversion above, simulate it here
if (e.Type == type)
{
return e;
}
else if (TypeHelper.GetNonNullableType(e.Type) == TypeHelper.GetNonNullableType(type))
{
return Expression.Constant(((ConstantExpression)e).Value, type);
}
}
var me = e as MemberExpression;
if (me != null)
{
// member accesses off of constant's are common, and yet since these partial evals
// are never re-used, using reflection to access the member is faster than compiling
// and invoking a lambda
var ce = me.Expression as ConstantExpression;
if (ce != null)
{
return Expression.Constant(me.Member.GetValue(ce.Value), type);
}
}
if (type.IsValueType)
{
e = Expression.Convert(e, typeof(object));
}
Expression<Func<object>> lambda = Expression.Lambda<Func<object>>(e);
#if NOREFEMIT
Func<object> fn = ExpressionEvaluator.CreateDelegate(lambda);
#else
Func<object> fn = lambda.Compile();
#endif
return Expression.Constant(fn(), type);
}
}
/// <summary>
/// Performs bottom-up analysis to determine which nodes can possibly
/// be part of an evaluated sub-tree.
/// </summary>
class Nominator : ExpressionVisitor
{
Func<Expression, bool> fnCanBeEvaluated;
HashSet<Expression> candidates;
bool cannotBeEvaluated;
private Nominator(Func<Expression, bool> fnCanBeEvaluated)
{
this.candidates = new HashSet<Expression>();
this.fnCanBeEvaluated = fnCanBeEvaluated;
}
internal static HashSet<Expression> Nominate(Func<Expression, bool> fnCanBeEvaluated, Expression expression)
{
Nominator nominator = new Nominator(fnCanBeEvaluated);
nominator.Visit(expression);
return nominator.candidates;
}
protected override Expression VisitConstant(ConstantExpression c)
{
return base.VisitConstant(c);
}
public override Expression Visit(Expression expression)
{
if (expression != null)
{
bool saveCannotBeEvaluated = this.cannotBeEvaluated;
this.cannotBeEvaluated = false;
base.Visit(expression);
if (!this.cannotBeEvaluated)
{
if (this.fnCanBeEvaluated(expression))
{
this.candidates.Add(expression);
}
else
{
this.cannotBeEvaluated = true;
}
}
this.cannotBeEvaluated |= saveCannotBeEvaluated;
}
return expression;
}
}
}
}

36
src/Libraries/IQToolkit/IQToolkit/Properties/AssemblyInfo.cs

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("IQueryable Toolkit")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("IQToolkit")]
[assembly: AssemblyCopyright("Copyright © Microsoft Corporation 2009 (MSPL)")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("46264a3c-2573-4343-b40e-7cab4e1e411c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

114
src/Libraries/IQToolkit/IQToolkit/Query.cs

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace IQToolkit
{
/// <summary>
/// Optional interface for IQueryProvider to implement Query<T>'s QueryText property.
/// </summary>
public interface IQueryText
{
string GetQueryText(Expression expression);
}
/// <summary>
/// A default implementation of IQueryable for use with QueryProvider
/// </summary>
public class Query<T> : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable, IOrderedQueryable<T>, IOrderedQueryable
{
IQueryProvider provider;
Expression expression;
public Query(IQueryProvider provider)
: this(provider, null)
{
}
public Query(IQueryProvider provider, Type staticType)
{
if (provider == null)
{
throw new ArgumentNullException("Provider");
}
this.provider = provider;
this.expression = staticType != null ? Expression.Constant(this, staticType) : Expression.Constant(this);
}
public Query(QueryProvider provider, Expression expression)
{
if (provider == null)
{
throw new ArgumentNullException("Provider");
}
if (expression == null)
{
throw new ArgumentNullException("expression");
}
if (!typeof(IQueryable<T>).IsAssignableFrom(expression.Type))
{
throw new ArgumentOutOfRangeException("expression");
}
this.provider = provider;
this.expression = expression;
}
public Expression Expression
{
get { return this.expression; }
}
public Type ElementType
{
get { return typeof(T); }
}
public IQueryProvider Provider
{
get { return this.provider; }
}
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)this.provider.Execute(this.expression)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this.provider.Execute(this.expression)).GetEnumerator();
}
public override string ToString()
{
if (this.expression.NodeType == ExpressionType.Constant &&
((ConstantExpression)this.expression).Value == this)
{
return "Query(" + typeof(T) + ")";
}
else
{
return this.expression.ToString();
}
}
public string QueryText
{
get
{
IQueryText iqt = this.provider as IQueryText;
if (iqt != null)
{
return iqt.GetQueryText(this.expression);
}
return "";
}
}
}
}

54
src/Libraries/IQToolkit/IQToolkit/QueryProvider.cs

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace IQToolkit
{
/// <summary>
/// A basic abstract LINQ query provider
/// </summary>
public abstract class QueryProvider : IQueryProvider, IQueryText
{
protected QueryProvider()
{
}
IQueryable<S> IQueryProvider.CreateQuery<S>(Expression expression)
{
return new Query<S>(this, expression);
}
IQueryable IQueryProvider.CreateQuery(Expression expression)
{
Type elementType = TypeHelper.GetElementType(expression.Type);
try
{
return (IQueryable)Activator.CreateInstance(typeof(Query<>).MakeGenericType(elementType), new object[] { this, expression });
}
catch (TargetInvocationException tie)
{
throw tie.InnerException;
}
}
S IQueryProvider.Execute<S>(Expression expression)
{
return (S)this.Execute(expression);
}
object IQueryProvider.Execute(Expression expression)
{
return this.Execute(expression);
}
public abstract string GetQueryText(Expression expression);
public abstract object Execute(Expression expression);
}
}

41
src/Libraries/IQToolkit/IQToolkit/ReflectionExtensions.cs

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
using System;
using System.Reflection;
namespace IQToolkit
{
public static class ReflectionExtensions
{
public static object GetValue(this MemberInfo member, object instance)
{
switch (member.MemberType)
{
case MemberTypes.Property:
return ((PropertyInfo)member).GetValue(instance, null);
case MemberTypes.Field:
return ((FieldInfo)member).GetValue(instance);
default:
throw new InvalidOperationException();
}
}
public static void SetValue(this MemberInfo member, object instance, object value)
{
switch (member.MemberType)
{
case MemberTypes.Property:
var pi = (PropertyInfo)member;
pi.SetValue(instance, value, null);
break;
case MemberTypes.Field:
var fi = (FieldInfo)member;
fi.SetValue(instance, value);
break;
default:
throw new InvalidOperationException();
}
}
}
}

150
src/Libraries/IQToolkit/IQToolkit/TypeHelper.cs

@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace IQToolkit
{
/// <summary>
/// Type related helper methods
/// </summary>
public static class TypeHelper
{
public static Type FindIEnumerable(Type seqType)
{
if (seqType == null || seqType == typeof(string))
return null;
if (seqType.IsArray)
return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
if (seqType.IsGenericType)
{
foreach (Type arg in seqType.GetGenericArguments())
{
Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
if (ienum.IsAssignableFrom(seqType))
{
return ienum;
}
}
}
Type[] ifaces = seqType.GetInterfaces();
if (ifaces != null && ifaces.Length > 0)
{
foreach (Type iface in ifaces)
{
Type ienum = FindIEnumerable(iface);
if (ienum != null) return ienum;
}
}
if (seqType.BaseType != null && seqType.BaseType != typeof(object))
{
return FindIEnumerable(seqType.BaseType);
}
return null;
}
public static Type GetSequenceType(Type elementType)
{
return typeof(IEnumerable<>).MakeGenericType(elementType);
}
public static Type GetElementType(Type seqType)
{
Type ienum = FindIEnumerable(seqType);
if (ienum == null) return seqType;
return ienum.GetGenericArguments()[0];
}
public static bool IsNullableType(Type type)
{
return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
public static bool IsNullAssignable(Type type)
{
return !type.IsValueType || IsNullableType(type);
}
public static Type GetNonNullableType(Type type)
{
if (IsNullableType(type))
{
return type.GetGenericArguments()[0];
}
return type;
}
public static Type GetNullAssignableType(Type type)
{
if (!IsNullAssignable(type))
{
return typeof(Nullable<>).MakeGenericType(type);
}
return type;
}
public static ConstantExpression GetNullConstant(Type type)
{
return Expression.Constant(null, GetNullAssignableType(type));
}
public static Type GetMemberType(MemberInfo mi)
{
FieldInfo fi = mi as FieldInfo;
if (fi != null) return fi.FieldType;
PropertyInfo pi = mi as PropertyInfo;
if (pi != null) return pi.PropertyType;
EventInfo ei = mi as EventInfo;
if (ei != null) return ei.EventHandlerType;
MethodInfo meth = mi as MethodInfo; // property getters really
if (meth != null) return meth.ReturnType;
return null;
}
public static object GetDefault(Type type)
{
bool isNullable = !type.IsValueType || TypeHelper.IsNullableType(type);
if (!isNullable)
return Activator.CreateInstance(type);
return null;
}
public static bool IsReadOnly(MemberInfo member)
{
switch (member.MemberType)
{
case MemberTypes.Field:
return (((FieldInfo)member).Attributes & FieldAttributes.InitOnly) != 0;
case MemberTypes.Property:
PropertyInfo pi = (PropertyInfo)member;
return !pi.CanWrite || pi.GetSetMethod() == null;
default:
return true;
}
}
public static bool IsInteger(Type type)
{
Type nnType = GetNonNullableType(type);
switch (Type.GetTypeCode(type))
{
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Byte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return true;
default:
return false;
}
}
}
}

31
src/Libraries/IQToolkit/license.txt

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
Microsoft Public License (Ms-PL)
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.

2
src/Libraries/IQToolkit/readme.txt

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
This is a stripped-down version of IQToolkit; it uses the .NET 4 ExpressionVisitor instead of the custom one.
This is necessary for .NET 4-style extension classes to expression trees as used by the SharpDevelop profiler.
Loading…
Cancel
Save