[英]Dynamic ExpandoObject in WCF
嘗試通過枚舉類型進程和動態數據的操作來 Ping/Pong 我的服務。
[ServiceContract ( CallbackContract = typeof ( iStackoverflowCallBack ) )]
public interface iStackoverflow
{
[OperationContract]
void Ping ( Process Operation , dynamic Data );
}
[ServiceContract ( )]
public interface iStackoverflowCallBack
{
[OperationContract]
void Pong ( Process Operation , dynamic Data );
}
為什么這個服務有連接問題?
dynamic
自動轉換為object
。ping
我的服務時,ping 根本沒有到達服務,但服務正常工作。解決方案 :
[DataContract]
public class SerializableDynamicObject : IDynamicMetaObjectProvider
{
[DataMember]
private IDictionary<string,object> dynamicProperties = new Dictionary<string,object>();
#region IDynamicMetaObjectProvider implementation
public DynamicMetaObject GetMetaObject (Expression expression)
{
return new SerializableDynamicMetaObject(expression,
BindingRestrictions.GetInstanceRestriction(expression, this), this);
}
#endregion
#region Helper methods for dynamic meta object support
internal object setValue(string name, object value)
{
dynamicProperties.Add(name, value);
return value;
}
internal object getValue(string name)
{
object value;
if(!dynamicProperties.TryGetValue(name, out value)) {
value = null;
}
return value;
}
internal IEnumerable<string> getDynamicMemberNames()
{
return dynamicProperties.Keys;
}
#endregion
}
public class SerializableDynamicMetaObject : DynamicMetaObject
{
Type objType;
public SerializableDynamicMetaObject(Expression expression, BindingRestrictions restrictions, object value)
: base(expression, restrictions, value)
{
objType = value.GetType();
}
public override DynamicMetaObject BindGetMember (GetMemberBinder binder)
{
var self = this.Expression;
var dynObj = (SerializableDynamicObject)this.Value;
var keyExpr = Expression.Constant(binder.Name);
var getMethod = objType.GetMethod("getValue", BindingFlags.NonPublic | BindingFlags.Instance);
var target = Expression.Call(Expression.Convert(self, objType),
getMethod,
keyExpr);
return new DynamicMetaObject(target,
BindingRestrictions.GetTypeRestriction(self, objType));
}
public override DynamicMetaObject BindSetMember (SetMemberBinder binder, DynamicMetaObject value)
{
var self = this.Expression;
var keyExpr = Expression.Constant(binder.Name);
var valueExpr = Expression.Convert(value.Expression, typeof(object));
var setMethod = objType.GetMethod("setValue", BindingFlags.NonPublic | BindingFlags.Instance);
var target = Expression.Call(Expression.Convert(self, objType),
setMethod,
keyExpr,
valueExpr);
return new DynamicMetaObject(target,
BindingRestrictions.GetTypeRestriction(self, objType));
}
public override IEnumerable<string> GetDynamicMemberNames ()
{
var dynObj = (SerializableDynamicObject)this.Value;
return dynObj.getDynamicMemberNames();
}
}
任何 WCF 操作協定的參數必須是 WCF 數據協定(或原始類型),否則數據將不會被序列化和傳輸。
擴展 Ahmed 的解決方案,了解如何使用它。
答案取自此頁面: https : //loosexaml.wordpress.com/2011/01/01/wcf-serialization-of-dlr-dynamic-types/
[DataContract]
public class SerializableDynamicObject : IDynamicMetaObjectProvider
{
[DataMember]
private IDictionary<string,object> dynamicProperties = new Dictionary<string,object>();
#region IDynamicMetaObjectProvider implementation
public DynamicMetaObject GetMetaObject (Expression expression)
{
return new SerializableDynamicMetaObject(expression,
BindingRestrictions.GetInstanceRestriction(expression, this), this);
}
#endregion
#region Helper methods for dynamic meta object support
internal object setValue(string name, object value)
{
dynamicProperties.Add(name, value);
return value;
}
internal object getValue(string name)
{
object value;
if(!dynamicProperties.TryGetValue(name, out value)) {
value = null;
}
return value;
}
internal IEnumerable<string> getDynamicMemberNames()
{
return dynamicProperties.Keys;
}
#endregion
}
public class SerializableDynamicMetaObject : DynamicMetaObject
{
Type objType;
public SerializableDynamicMetaObject(Expression expression, BindingRestrictions restrictions, object value)
: base(expression, restrictions, value)
{
objType = value.GetType();
}
public override DynamicMetaObject BindGetMember (GetMemberBinder binder)
{
var self = this.Expression;
var dynObj = (SerializableDynamicObject)this.Value;
var keyExpr = Expression.Constant(binder.Name);
var getMethod = objType.GetMethod("getValue", BindingFlags.NonPublic | BindingFlags.Instance);
var target = Expression.Call(Expression.Convert(self, objType),
getMethod,
keyExpr);
return new DynamicMetaObject(target,
BindingRestrictions.GetTypeRestriction(self, objType));
}
public override DynamicMetaObject BindSetMember (SetMemberBinder binder, DynamicMetaObject value)
{
var self = this.Expression;
var keyExpr = Expression.Constant(binder.Name);
var valueExpr = Expression.Convert(value.Expression, typeof(object));
var setMethod = objType.GetMethod("setValue", BindingFlags.NonPublic | BindingFlags.Instance);
var target = Expression.Call(Expression.Convert(self, objType),
setMethod,
keyExpr,
valueExpr);
return new DynamicMetaObject(target,
BindingRestrictions.GetTypeRestriction(self, objType));
}
public override IEnumerable<string> GetDynamicMemberNames ()
{
var dynObj = (SerializableDynamicObject)this.Value;
return dynObj.getDynamicMemberNames();
}
}
一個簡單的使用方法:
dynamic d = new SerializableDynamicObject();
d.Name = “SomeData”;
d.Address = new SerializableDynamicObject();
d.Address.Line1 = “123 Spring St.”;
dynamic a = new SerializableDynamicObject();
a.Items = new List(new object[] { d, d });
return a;
但是請記住,WCF 需要了解數據類型,因為它是最基本的數據類型,如string
、 int
等,這不是問題。 但是,如果您在動態對象中使用自定義數據類型,則必須使用[KnownType(typeof(XXX))]
指令進行定義。 這適用於enums
、 List<>
和任何其他自定義類。
例如:
[KnownType(typeof(MyCustomEnum))]
[KnownType(typeof(List<object>))]
[DataContract]
public class SerializableDynamicObject : IDynamicMetaObjectProvider
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.