在某些场合中,我们需要提供以object为参数的方法。不过在WCF中,由于需要序列化与反序列化,因此它要求所有WCF传递的参数类型都是已知的,无法传递object这种未知类型。即使用了KnownType来标记自定义对象,也无法调用。以下代码无法正常执行:
[DataContract] public class Product { [DataMember] public string Name; }[ServiceContract]
public interface IProductInfo { [OperationContract] string GetProductTypeName(Object obj); } [KnownType(typeof(Product))] public class ProductInfo : IProductInfo { public string GetProductTypeName(Object obj) { return obj.ToString(); } }调用时:
ProductInfoClient client = new ProductInfoClient (); client.GetProductTypeName("传字符串类型,调用成功"); client.GetProductTypeName(new Product()); //报错不过,可以通过定义一个中间类型来传递object对象。方法就是在这个类型中包含一个object的成员,并且定义该成员为KnownType。代码如下:
[DataContract]
[KnownType(typeof(Product))] //必须标记Product类型 public class RequestData { [DataMember] public object RequestObject; }通过传递RequestData,就能变相实现object对象的传递。
[ServiceContract]
public interface IProductInfo { [OperationContract] string GetProductTypeName(RequestData requestData); } public class ProductInfo : IProductInfo { public string GetProductTypeName(RequestData requestData) { return requestData.RequestObject.ToString(); } } 不过,你会发现任何自定义对象都必须在RequestData中预先设定为KnownType,否则WCF无法序列化。这显然还不够灵活。为了让方法可以方便的调用,而不需要担心是否标记了KnownType,我们可以通过定义一个方法并把这个方法名作为KnownType参数来解决此问题。这里用到KnownType的另一个重载方法: KnownTypeAttribute(string methodName); 这个方法必须满足以下条件: a 必须是static,因为需要在对象实例化之前调用。 b 必须是不带任何参数的。 C 返回类型必须是可被IEnumerable接受的,(也就是实现了IEnumerable接口的)。改造后RequestData如下:
[DataContract]
[KnownType("GetKnownType")] public class RequestData { //增加构造函数方便使用 public RequestData(object requestObj) { RequestObject = requestObj; } [DataMember] public object RequestObject;private static Type[] GetKnownType() { //将自定义对象的程序集下的所有类型标记为KnownType。 return Assembly.Load("DataEntityAssemblyName").GetTypes(); } }
在GetKnownType函数中,程序将自定义类型的程序集包含的类型全部返回,这下就省事多了。。