5

尝试通过枚举类型进程和动态数据的操作来 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();
    }
}
4

2 回答 2

1

任何 WCF 操作协定的参数必须是 WCF 数据协定(或原始类型),否则数据将不会被序列化和传输。

http://msdn.microsoft.com/en-us/library/ms733127.aspx

于 2012-07-15T12:03:50.210 回答
1

扩展 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 需要了解数据类型,因为它是最基本的数据类型,例如 等stringint这不是问题。但是,如果您在动态对象中使用自定义数据类型,则必须在使用[KnownType(typeof(XXX))]指令中进行定义。这适用于enumsList<>任何其他自定义类。

例如:

[KnownType(typeof(MyCustomEnum))]
[KnownType(typeof(List<object>))]
[DataContract]
public class SerializableDynamicObject : IDynamicMetaObjectProvider
...
于 2019-10-30T16:13:06.287 回答