استفاده از Lambda Expression در پروژه های مبتنی بر WCF
نویسنده: مسعود پاکدل
تاریخ: ۱۳۹۲/۰۳/۳۰ ۱۹:۱۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
با توجه به این که دادهها سریالایز میشوند، در نتیجه امکان انقال داده هایی که از نوع object هستند در WCF وجود ندارد. بلکه نوع داده باید صراحتا ذکر شود و این نوع باید قابیلت سریالایز شدن را دارا باشد.برای مثال شما نمیتونید متدی داشته باشید که پارامتر ورودی آن از نوع delegate باشد یا کلاسی باشد که صفت [Serializable] در بالای اون قرار نداشته باشد یا کلاسی باشد که صفت DataContract برای خود کلاس و صفت DataMember برای خاصیتهای اون تعریف نشده باشد. حالا سوال مهم این است اگر متدی داشته باشیم که پارامتر ورودی آن حتما باید از نوع delegate باشد چه باید کرد؟
برای تشریح بهتر مسئله یک مثال میزنم؟
سرویسی داریم برای اطلاعات کتاب ها. قصد داریم متدی بنوسیم که پارامتر
ورودی آن از نوع Lambda Expression است تا Query مورد نظر کاربر از سمت
کلاینت به سمت سرور دریافت کند و خروجی مورد نظر را با توجه به Query ورودی
به کلاینت برگشت دهد.( متدی متداول در اکثر پروژه ها). به صورت زیر عمل میکنیم.
*ابتدا یک Blank Solution ایجاد کنید.
*یک ClassLibrary به نام Model ایجاد کنید و کلاسی به نام Book در آن بسازید .(همانطور که میبینید کلاس مورد نظر سریالایز شده است):
[DataContract]
public class Book
{
[DataMember]
public int Code { get; set; }
[DataMember]
public string Title { get; set; }
}using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.ServiceModel;
namespace WcfLambdaExpression
{
[ServiceContract]
public interface IBookService
{
[OperationContract]
IEnumerable<Book> GetByExpression( Expression<Func<Book, bool>> expression );
}
}using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace WcfLambdaExpression
{
public class BookService : IBookService
{
public BookService()
{
ListOfBook = new List<Book>();
}
public List<Book> ListOfBook
{
get;
private set;
}
public IEnumerable<Book> GetByExpression( Expression<Func<Book, bool>> expression )
{
ListOfBook.AddRange( new Book[]
{
new Book(){Code = 1 , Title = "Book1"},
new Book(){Code = 2 , Title = "Book2"},
new Book(){Code = 3 , Title = "Book3"},
new Book(){Code = 4 , Title = "Book4"},
new Book(){Code = 5 , Title = "Book5"},
} );
return ListOfBook.AsQueryable().Where( expression );
}
}
}Type 'System.Linq.Expressions.Expression`1[System.Func`2[WcfLambdaExpression.Book,System.Boolean]]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types
[ServiceContract]
public interface IBookService
{
[OperationContract]
IEnumerable<Book> GetByExpression( XElement expression );
}using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Xml.Linq;
namespace WcfLambdaExpression
{
public class BookService : IBookService
{
public BookService()
{
ListOfBook = new List<Book>();
}
public List<Book> ListOfBook
{
get;
private set;
}
public IEnumerable<Book> GetByExpression( XElement expression )
{
ListOfBook.AddRange( new Book[]
{
new Book(){Code = 1 , Title = "Book1"},
new Book(){Code = 2 , Title = "Book2"},
new Book(){Code = 3 , Title = "Book3"},
new Book(){Code = 4 , Title = "Book4"},
new Book(){Code = 5 , Title = "Book5"},
} );
Common.ExpressionSerializer serializer = new Common.ExpressionSerializer();
return ListOfBook.AsQueryable().Where( serializer.Deserialize( expression ) as Expression<Func<Book, bool>> );
}
}using System;
using System.Linq.Expressions;
using TestExpression.MyBookService;
namespace TestExpression
{
class Program
{
static void Main( string[] args )
{
BookServiceClient bookService = new BookServiceClient();
Expression<Func<Book, bool>> expression = x => x.Code > 2 && x.Code < 5;
Common.ExpressionSerializer serializer = new Common.ExpressionSerializer();
bookService.GetByExpression( serializer.Serialize( expression ) );
}
}
}خروجی هم به صورت زیر خواهد بود:
string json = JsonConvert.SerializeObject(serializer.Serialize(predicate3)); predicate3 = JsonConvert.DeserializeObject<Expression<Func<Entity, bool>>>(json);
Expression<Func<Book, bool>> expression = x => x.Code > 2 && x.Code < 5; var expressionSerializer = new Common.ExpressionSerializer(); var xml = expressionSerializer.Serialize(expression); var xmlToJson = JsonConvert.SerializeObject(xml); var xmlObject = JsonConvert.DeserializeObject<XElement>(xmlToJson); var exp2 = expressionSerializer.Deserialize(xmlObject) as Expression<Func<Book, bool>>;