[英]Dynamic ExpandoObject in WCF
Trying to Ping / Pong my service with an operation of enum type process and dynamic data.尝试通过枚举类型进程和动态数据的操作来 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 );
}
Why this service having issues connecting ?为什么这个服务有连接问题?
dynamic
converted automatically to object
.dynamic
自动转换为object
。ping
ing my service from consumer, the ping doesn't reach the service at all but the service is working properly.ping
我的服务时,ping 根本没有到达服务,但服务正常工作。 Solution :解决方案 :
[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();
}
}
The arguments for any WCF Operation Contract must be WCF Data Contract (or primitive types) or else the data will not be serialized and transferred.任何 WCF 操作协定的参数必须是 WCF 数据协定(或原始类型),否则数据将不会被序列化和传输。
http://msdn.microsoft.com/en-us/library/ms733127.aspx http://msdn.microsoft.com/en-us/library/ms733127.aspx
To expand on the solution from Ahmed on how to use it.扩展 Ahmed 的解决方案,了解如何使用它。
The answer is taken from this page: https://loosexaml.wordpress.com/2011/01/01/wcf-serialization-of-dlr-dynamic-types/答案取自此页面: 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();
}
}
A simple way to use it:一个简单的使用方法:
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;
However keep in mind that WCF requires knowledge of data types, since it most most basic data types like string
, int
etc it isn't a problem.但是请记住,WCF 需要了解数据类型,因为它是最基本的数据类型,如
string
、 int
等,这不是问题。 But if you're using a custom data type in your dynamic object, you must define in using the [KnownType(typeof(XXX))]
directive.但是,如果您在动态对象中使用自定义数据类型,则必须使用
[KnownType(typeof(XXX))]
指令进行定义。 This applies to enums
, List<>
and any other custom classes.这适用于
enums
、 List<>
和任何其他自定义类。
For example:例如:
[KnownType(typeof(MyCustomEnum))]
[KnownType(typeof(List<object>))]
[DataContract]
public class SerializableDynamicObject : IDynamicMetaObjectProvider
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.