Skip to content

Commit

Permalink
Initial check-in of source corresponding to NuGet package v1.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
damieng committed Sep 15, 2011
0 parents commit 85e5b34
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Microsoft.Linq.Translations.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Linq.Translations", "Microsoft.Linq.Translations\Microsoft.Linq.Translations.csproj", "{261B06CF-E3FF-4A88-935A-A7E735CC2981}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{261B06CF-E3FF-4A88-935A-A7E735CC2981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{261B06CF-E3FF-4A88-935A-A7E735CC2981}.Debug|Any CPU.Build.0 = Debug|Any CPU
{261B06CF-E3FF-4A88-935A-A7E735CC2981}.Release|Any CPU.ActiveCfg = Release|Any CPU
{261B06CF-E3FF-4A88-935A-A7E735CC2981}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
39 changes: 39 additions & 0 deletions Microsoft.Linq.Translations/CompiledExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
namespace Microsoft.Linq.Translations {
using System;
using System.Linq.Expressions;

/// <summary>
/// Provides the common boxed version of get.
/// </summary>
public abstract class CompiledExpression {
internal abstract LambdaExpression BoxedGet { get; }
}

/// <summary>
/// Represents an expression and its compiled function.
/// </summary>
/// <typeparam name="TClass">Class the expression relates to.</typeparam>
/// <typeparam name="TProperty">Return type of the expression.</typeparam>
public sealed class CompiledExpression<T, TResult> : CompiledExpression {
private Expression<Func<T, TResult>> expression;
private Func<T, TResult> function;

public CompiledExpression() {
}

public CompiledExpression(Expression<Func<T, TResult>> expression) {
this.expression = expression;
function = expression.Compile();
}

public TResult Evaluate(T instance) {
return function(instance);
}

internal override LambdaExpression BoxedGet {
get { return expression; }
}
}
}
38 changes: 38 additions & 0 deletions Microsoft.Linq.Translations/DefaultTranslationOf.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
namespace Microsoft.Linq.Translations {
using System;
using System.Linq.Expressions;
using System.Reflection;

/// <summary>
/// Simple fluent way to access the default translation map.
/// </summary>
/// <typeparam name="T">Class the expression uses.</typeparam>
public static class DefaultTranslationOf<T> {
public static CompiledExpression<T, TResult> Property<TResult>(Expression<Func<T, TResult>> property, Expression<Func<T, TResult>> expression) {
return TranslationMap.defaultMap.Add(property, expression);
}

public static IncompletePropertyTranslation<TResult> Property<TResult>(Expression<Func<T, TResult>> property) {
return new IncompletePropertyTranslation<TResult>(property);
}

public static TResult Evaluate<TResult>(T instance, MethodBase method) {
var compiledExpression = TranslationMap.defaultMap.Get<T, TResult>(method);
return compiledExpression.Evaluate(instance);
}

public class IncompletePropertyTranslation<TResult> {
private Expression<Func<T, TResult>> property;

internal IncompletePropertyTranslation(Expression<Func<T, TResult>> property) {
this.property = property;
}

public CompiledExpression<T, TResult> Is(Expression<Func<T, TResult>> expression) {
return DefaultTranslationOf<T>.Property(property, expression);
}
}
}
}
81 changes: 81 additions & 0 deletions Microsoft.Linq.Translations/ExpressiveExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
namespace Microsoft.Linq.Translations {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;

/// <summary>
/// Extension methods over IQueryable to turn on expression translation via a
/// specified or default TranslationMap.
/// </summary>
public static class ExpressiveExtensions {
public static IQueryable<T> WithTranslations<T>(this IQueryable<T> source) {
return source.Provider.CreateQuery<T>(WithTranslations(source.Expression));
}

public static IQueryable<T> WithTranslations<T>(this IQueryable<T> source, TranslationMap map) {
return source.Provider.CreateQuery<T>(WithTranslations(source.Expression, map));
}

public static Expression WithTranslations(Expression expression) {
return WithTranslations(expression, TranslationMap.defaultMap);
}

public static Expression WithTranslations(Expression expression, TranslationMap map) {
return new TranslatingVisitor(map).Visit(expression);
}

private static void EnsureTypeInitialized(Type type) {
try {
// Ensure the static members are accessed class' ctor
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
}
catch (TypeInitializationException) {

}
}

/// <summary>
/// Extends the expression visitor to translate properties to expressions
/// according to the provided translation map.
/// </summary>
private class TranslatingVisitor : ExpressionVisitor {
private readonly Stack<KeyValuePair<ParameterExpression, Expression>> bindings = new Stack<KeyValuePair<ParameterExpression, Expression>>();
private readonly TranslationMap map;

internal TranslatingVisitor(TranslationMap map) {
this.map = map;
}

protected override Expression VisitMember(MemberExpression node) {
EnsureTypeInitialized(node.Member.DeclaringType);

CompiledExpression cp;
if (map.TryGetValue(node.Member, out cp)) {
return VisitCompiledExpression(cp, node.Expression);
}

if (typeof(CompiledExpression).IsAssignableFrom(node.Member.DeclaringType)) {
return VisitCompiledExpression(cp, node.Expression);
}

return base.VisitMember(node);
}

private Expression VisitCompiledExpression(CompiledExpression ce, Expression expression) {
bindings.Push(new KeyValuePair<ParameterExpression, Expression>(ce.BoxedGet.Parameters.Single(), expression));
var body = Visit(ce.BoxedGet.Body);
bindings.Pop();
return body;
}

protected override Expression VisitParameter(ParameterExpression p) {
var binding = bindings.Where(b => b.Key == p).FirstOrDefault();
return (binding.Value == null) ? base.VisitParameter(p) : Visit(binding.Value);
}
}
}
}
98 changes: 98 additions & 0 deletions Microsoft.Linq.Translations/Microsoft.Linq.Translations.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?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.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{261B06CF-E3FF-4A88-935A-A7E735CC2981}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.Linq.Translations</RootNamespace>
<AssemblyName>Microsoft.Linq.Translations</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</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>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CompiledExpression.cs" />
<Compile Include="DefaultTranslationOf.cs" />
<Compile Include="ExpressiveExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TranslationMap.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<licenseUrl>http://www.microsoft.com/opensource/licenses.mspx</licenseUrl>
<projectUrl>http://damieng.com/blog/2009/06/24/client-side-properties-and-any-remote-linq-provider</projectUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<tags>linq computedproperties</tags>
</metadata>
</package>
36 changes: 36 additions & 0 deletions Microsoft.Linq.Translations/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -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("Microsoft.Linq.Translations")]
[assembly: AssemblyDescription("Provides a LINQ provider independent way of translating computed properties into complex expressions.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("David Fowler, Damien Guard")]
[assembly: AssemblyProduct("Microsoft.Linq.Translations")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2009")]
[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("3aea9788-d834-4e84-ac13-8aa2bd2fc577")]

// 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.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
30 changes: 30 additions & 0 deletions Microsoft.Linq.Translations/TranslationMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// This source code is made available under the terms of the Microsoft Public License (MS-PL)
namespace Microsoft.Linq.Translations {
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

/// <summary>
/// Maintains a list of mappings between properties and their compiled expressions.
/// </summary>
public class TranslationMap : Dictionary<MemberInfo, CompiledExpression> {
internal static TranslationMap defaultMap = new TranslationMap();

public CompiledExpression<T, TResult> Get<T, TResult>(MethodBase method) {
var propertyInfo = method.DeclaringType.GetProperty(method.Name.Replace("get_", String.Empty));
return this[propertyInfo] as CompiledExpression<T, TResult>;
}

public void Add<T, TResult>(Expression<Func<T, TResult>> property, CompiledExpression<T, TResult> compiledExpression) {
base.Add(((MemberExpression)property.Body).Member, compiledExpression);
}

public CompiledExpression<T, TResult> Add<T, TResult>(Expression<Func<T, TResult>> property, Expression<Func<T, TResult>> expression) {
var compiledExpression = new CompiledExpression<T, TResult>(expression);
Add(property, compiledExpression);
return compiledExpression;
}
}
}

0 comments on commit 85e5b34

Please sign in to comment.