What Was I Thinking?

Follies & Foils of .NET Development

  Home  |   Contact  |   Syndication    |   Login
  74 Posts | 0 Stories | 192 Comments | 0 Trackbacks

News

Archives

Post Categories

Check These Out

Gurus

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
}











  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
posted on Saturday, October 10, 2009 11:41 AM

Feedback

# re: Using Dynamic Linq in Silverlight Projects 11/12/2009 4:18 AM youngtarun
ReliabilityContract still gives error. Do you have alternate for that?

# re: Using Dynamic Linq in Silverlight Projects 11/12/2009 6:52 AM wtfChris
Oops.. Looks like I forgot to include ReliabilityContract source. I've updated the posting to include the missing code snippet.

Happy Linq'ing

# re: Using Dynamic Linq in Silverlight Projects 2/13/2010 3:26 PM vikzer
thanks!!, this solves me, a big problem.

# re: Using Dynamic Linq in Silverlight Projects 9/21/2010 1:53 PM Bill
Thanks for the posting, just what I neeed.

# re: Using Dynamic Linq in Silverlight Projects 12/2/2010 4:59 AM caje
Thanks for working this out. Spared some time from me since I don't need to start sniffing around with Reflector.

# re: Using Dynamic Linq in Silverlight Projects 3/8/2011 11:58 PM Lance
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.

# re: Using Dynamic Linq in Silverlight Projects 3/16/2011 6:29 AM Madhu
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.

# re: Using Dynamic Linq in Silverlight Projects 3/17/2011 10:19 AM darren zully
You can download ReaderWriterLockSlim from http://calcium.codeplex.com/SourceControl/list/changesets and replace ReaderWriterLock. That solution works!!

D.

# re: Using Dynamic Linq in Silverlight Projects 4/15/2011 9:16 AM Javed
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).


# re: Using Dynamic Linq in Silverlight Projects 4/18/2011 2:30 AM Javed
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.....

# re: Using Dynamic Linq in Silverlight Projects 8/18/2011 10:38 PM Nick Wood
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

# re: Using Dynamic Linq in Silverlight Projects 2/2/2012 6:02 PM Truyenle
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

# re: Using Dynamic Linq in Silverlight Projects 2/3/2012 5:02 PM Truyenle
Is there any suggestion where to start added these into Dynamic.cs?
Thanks

# re: Using Dynamic Linq in Silverlight Projects 2/7/2012 2:17 PM sj
I have the same issue as what Nick and Lance ran into. Can someone help fix the issue?

# re: Using Dynamic Linq in Silverlight Projects 2/8/2012 8:37 AM Gautham
I was stuggling to create an dynamic query under silverlight. This article helped me to solve this problem.
Thankyou very much.

Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: