What Was I Thinking?

Follies & Foils of .NET Development
posts - 95 , comments - 352 , trackbacks - 0

Using Dynamic Linq in Silverlight Projects

Recently I had the need to implement support for Dynamic Linq queries in my framework project.  For the uninitiated, Dynamic Linq allows me to write statements like this:

var query =
               db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
               OrderBy("CompanyName").
               Select("New(CompanyName as Name, Phone)");

where I can specify the predicates and selectors as string values.   Microsoft has published a helper class that enables DynamicLinq support here -->C# Dynamic Query Library (included in the -LinqSamples-DynamicQuery directory).

 

Buried in this code is a class Called Dynamic.cs.  Include this code file into your project and you’ll have Dyanmic Linq support, Unless…

 

Unless, you’re developing a silverlight application.  The dynamic class makes use of a ReaderWriterLock class that isn’t available in the Silverlight implementation of System.Threading.

Using Reflector, I extracted the disassembled code for ReaderWriterLock and made a version that will compile and run under silverlight.  The only adjustment was commenting out the HostProtection attribute since it wasn’t available due to its protection level.  In my testing I haven’t run into any problems as the result of removing this attribute.

Here’s the code you’ll want to add to your silverlight libraries in order to allow the compilation of Dynamic.cs and support Dynamic Linq in your silverlight project:

 

ReaderWriterLock.cs

using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Security.Permissions;
using System;
//[ComVisible(true), HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
[ComVisible(true)]
public sealed class ReaderWriterLock : CriticalFinalizerObject
{
    // Fields
    private int _dwLLockID;
    private int _dwState;
    private int _dwULockID;
    private int _dwWriterID;
    private int _dwWriterSeqNum;
    private IntPtr _hObjectHandle;
    private IntPtr _hReaderEvent;
    private IntPtr _hWriterEvent;
    private short _wWriterLevel;
 
    // Methods
    public ReaderWriterLock()
    {
        this.PrivateInitialize();
    }
 
    public void AcquireReaderLock(int millisecondsTimeout)
    {
        this.AcquireReaderLockInternal(millisecondsTimeout);
    }
 
    public void AcquireReaderLock(TimeSpan timeout)
    {
        long totalMilliseconds = (long)timeout.TotalMilliseconds;
        if ((totalMilliseconds < -1L) || (totalMilliseconds > 0x7fffffffL))
        {
            throw new ArgumentOutOfRangeException("timeout", "ArgumentOutOfRange_NeedNonNegOrNegative1");
        }
        this.AcquireReaderLockInternal((int)totalMilliseconds);
    }
 
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void AcquireReaderLockInternal(int millisecondsTimeout);
    public void AcquireWriterLock(int millisecondsTimeout)
    {
        this.AcquireWriterLockInternal(millisecondsTimeout);
    }
 
    public void AcquireWriterLock(TimeSpan timeout)
    {
        long totalMilliseconds = (long)timeout.TotalMilliseconds;
        if ((totalMilliseconds < -1L) || (totalMilliseconds > 0x7fffffffL))
        {
            throw new ArgumentOutOfRangeException("timeout", "ArgumentOutOfRange_NeedNonNegOrNegative1");
        }
        this.AcquireWriterLockInternal((int)totalMilliseconds);
    }
 
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void AcquireWriterLockInternal(int millisecondsTimeout);
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern bool AnyWritersSince(int seqNum);
    public void DowngradeFromWriterLock(ref LockCookie lockCookie)
    {
        this.DowngradeFromWriterLockInternal(ref lockCookie);
    }
 
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void DowngradeFromWriterLockInternal(ref LockCookie lockCookie);
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void FCallReleaseLock(ref LockCookie result);
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void FCallUpgradeToWriterLock(ref LockCookie result, int millisecondsTimeout);
    ~ReaderWriterLock()
    {
        this.PrivateDestruct();
    }
 
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void PrivateDestruct();
    [MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    private extern bool PrivateGetIsReaderLockHeld();
    [MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    private extern bool PrivateGetIsWriterLockHeld();
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern int PrivateGetWriterSeqNum();
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void PrivateInitialize();
    public LockCookie ReleaseLock()
    {
        LockCookie result = new LockCookie();
        this.FCallReleaseLock(ref result);
        return result;
    }
 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    public void ReleaseReaderLock()
    {
        this.ReleaseReaderLockInternal();
    }
 
    [MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    private extern void ReleaseReaderLockInternal();
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    public void ReleaseWriterLock()
    {
        this.ReleaseWriterLockInternal();
    }
 
    [MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    private extern void ReleaseWriterLockInternal();
    public void RestoreLock(ref LockCookie lockCookie)
    {
        this.RestoreLockInternal(ref lockCookie);
    }
 
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void RestoreLockInternal(ref LockCookie lockCookie);
    public LockCookie UpgradeToWriterLock(int millisecondsTimeout)
    {
        LockCookie result = new LockCookie();
        this.FCallUpgradeToWriterLock(ref result, millisecondsTimeout);
        return result;
    }
 
    public LockCookie UpgradeToWriterLock(TimeSpan timeout)
    {
        long totalMilliseconds = (long)timeout.TotalMilliseconds;
        if ((totalMilliseconds < -1L) || (totalMilliseconds > 0x7fffffffL))
        {
            throw new ArgumentOutOfRangeException("timeout","ArgumentOutOfRange_NeedNonNegOrNegative1");
        }
        return this.UpgradeToWriterLock((int)totalMilliseconds);
    }
 
    // Properties
    public bool IsReaderLockHeld
    {
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        get
        {
            return this.PrivateGetIsReaderLockHeld();
        }
    }
 
    public bool IsWriterLockHeld
    {
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        get
        {
            return this.PrivateGetIsWriterLockHeld();
        }
    }
 
    public int WriterSeqNum
    {
        get
        {
            return this.PrivateGetWriterSeqNum();
        }
    }
}
 

and LockCookie.cs

using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential), ComVisible(true)]
public struct LockCookie
{
    private int _dwFlags;
    private int _dwWriterSeqNum;
    private int _wReaderAndWriterLevel;
    private int _dwThreadID;
    public override int GetHashCode()
    {
        return (((this._dwFlags + this._dwWriterSeqNum) + this._wReaderAndWriterLevel) + this._dwThreadID);
    }
 
    public override bool Equals(object obj)
    {
        return ((obj is LockCookie) && this.Equals((LockCookie)obj));
    }
 
    public bool Equals(LockCookie obj)
    {
        return ((((obj._dwFlags == this._dwFlags) && (obj._dwWriterSeqNum == this._dwWriterSeqNum)) && (obj._wReaderAndWriterLevel == this._wReaderAndWriterLevel)) && (obj._dwThreadID == this._dwThreadID));
    }
 
    public static bool operator ==(LockCookie a, LockCookie b)
    {
        return a.Equals(b);
    }
 
    public static bool operator !=(LockCookie a, LockCookie b)
    {
        return !(a == b);
    }
}
 
 

 

and ReliabilityContract.cs

using System;
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, Inherited = false)]
public sealed class ReliabilityContractAttribute : Attribute
{
// Fields
private Cer _cer;
private Consistency _consistency;

// Methods
public ReliabilityContractAttribute(Consistency consistencyGuarantee, Cer cer)
{
this._consistency = consistencyGuarantee;
this._cer = cer;
}

// Properties
public Cer Cer
{
get
{
return this._cer;
}
}

public Consistency ConsistencyGuarantee
{
get
{
return this._consistency;
}
}
}
public enum Consistency
{
MayCorruptProcess,
MayCorruptAppDomain,
MayCorruptInstance,
WillNotCorruptState
}


public enum Cer
{
None,
MayFail,
Success
}











Print | posted on Saturday, October 10, 2009 11:41 AM | Filed Under [ Silverlight ]

Feedback

Gravatar

# re: Using Dynamic Linq in Silverlight Projects

ReliabilityContract still gives error. Do you have alternate for that?
11/12/2009 4:18 AM | youngtarun
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

Oops.. Looks like I forgot to include ReliabilityContract source. I've updated the posting to include the missing code snippet.

Happy Linq'ing
11/12/2009 6:52 AM | wtfChris
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

thanks!!, this solves me, a big problem.
2/13/2010 3:26 PM | vikzer
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

Thanks for the posting, just what I neeed.
9/21/2010 1:53 PM | Bill
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

Thanks for working this out. Spared some time from me since I don't need to start sniffing around with Reflector.
12/2/2010 4:59 AM | caje
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

Hi,

I tried to use your code but keep getting the error "Inheritance security rules violated while overriding member: 'ReaderWriterLock..ctor()'. Security accessibility of the overriding method must match the security accessibility of the method being overriden." Am I doing something wrong? Please help.
3/8/2011 11:58 PM | Lance
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

Hi,

I am getting the same error that Lance got. Is there any workaround for that? Lance please let me know if you found any solution for the same.
3/16/2011 6:29 AM | Madhu
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

You can download ReaderWriterLockSlim from http://calcium.codeplex.com/SourceControl/list/changesets and replace ReaderWriterLock. That solution works!!

D.
3/17/2011 10:19 AM | darren zully
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

What are the equvalents of the LINQ functions like Contains(), StartsWith() etc.
When I write db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
it works but it does not works for equals()

db.Customers.Where("City equals @0 and Orders.Count >= @1", "London", 10).
4/15/2011 9:16 AM | Javed
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

I found it is like this..
db.Customers.Where("City.equals (@0) and Orders.Count >= @1", "London", 10).

Similarly
"City.Contains(@0)", "London"

It works.....
4/18/2011 2:30 AM | Javed
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

I too am getting: "'ReaderWriterLock..ctor()'. Security accessibility of the overriding method must match the security accessibility of the method being overriden."

I have tried the latest ReaderWriterLockSlim file from the latest changeset, but there are missing methods.

Please help me
8/18/2011 10:38 PM | Nick Wood
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

This is cool. It works most of the cases. Thanks.

I do have an issue if the string is as "
(BYTE_0 & 1<<0) > 0

Then it doesn't work.
Seem that Dynamic.cs doens't implement Shift (<<, >>) and bitwise operators?

Any help on this is very much appreciated.
Thanks
2/2/2012 6:02 PM | Truyenle
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

Is there any suggestion where to start added these into Dynamic.cs?
Thanks
2/3/2012 5:02 PM | Truyenle
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

I have the same issue as what Nick and Lance ran into. Can someone help fix the issue?
2/7/2012 2:17 PM | sj
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

I was stuggling to create an dynamic query under silverlight. This article helped me to solve this problem.
Thankyou very much.
2/8/2012 8:37 AM | Gautham
Gravatar

# re: Using Dynamic Linq in Silverlight Projects

thanks very much!!!!!
6/8/2013 11:09 AM | littlebeer
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: