WCF中的动态ExpandoObject

5
尝试使用枚举类型的 process 操作和动态数据来 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();
    }
}

请查看http://loosexaml.wordpress.com/2011/01/01/wcf-serialization-of-dlr-dynamic-types/,了解Ahmend发布的代码的解释。 - rene
2个回答

1

1
那么如何发送已知数据的未知数据包? - Ahmed Ghoneim
数据从哪里来?你能将它序列化成字符串吗?我在快速搜索中找到了这个。看看它是否适用于你:https://loosexaml.wordpress.com/2011/01/01/wcf-serialization-of-dlr-dynamic-types/ - Glenn Ferrie

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
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接