序列化(WCF)自定义属性。有可能吗?可行吗?

时间:2016-12-05 19:42:04

标签: c# wcf serialization attributes

我已搜索过两者(谷歌和此处的SO),问题在于大多数问题确实与序列化使用属性(XML属性或DataContract)有关,而不是自定义属性的实际序列化。请参阅下面的几个相似的问题

我们正处于某个项目的计划阶段。

其中一项要求促使我们在可能的情况下提出问题,并建议序列化(针对WCF)自定义属性。

如果是这样,我们是否还需要KnownType属性来装饰服务合同?

例如,我们有自定义属性,在我们的DTO对象中使用:

  [DataContract] // <- is this allowed/adviseable
  [AttributeUsage(AttributeTargets.Property)]
  public class DtoPropertyAttribute : Attribute
  {
    [DataMember] // <- this too
    public int MaximumLength { get; set; }

    public DtoPropertyAttribute(int maximumLength)
    {
      this.MaximumLength = maximumLength;
    }   

  }

在某些时候我们会使用......

Object[] GetCustomAttributes(bool inherit);

...来自命名空间:

System.Reflection.MemberInfo

...如下(WCF服务端):

 //property is of type System.Reflection.ProperInfo
 var attributes property.GetCustomAttributes(false);

然后我们检查属性是否具有属性

 //..
 //some logic here that iterates/gets a single attribute 'attribute'
 //...

 if(attribute is DtoPropertyAttribute
 {
    //do stuff
 }

我们注意到属性是可序列化的:

namespace System {
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 

namespace System { 

using System;
using System.Reflection; 
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Diagnostics.Contracts; 
using System.Security;
using System.Security.Permissions; 

    [Serializable] //<--- See me please!!
    [AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple=false)] 
    [ClassInterface(ClassInterfaceType.None)]
    [ComDefaultInterface(typeof(_Attribute))]
    [System.Runtime.InteropServices.ComVisible(true)]
    public abstract class Attribute : _Attribute 
    {
        //...
    }

脚注:类似的问题没有回答我的问题:

  1. Serialize Custom Attribute Values(与JSON相关)

1 个答案:

答案 0 :(得分:2)

写了一个小概念证明,并且可以愉快地得出结论:属性(和它们的值)可以被序列化而没有问题!

答案是可以的!自定义属性上的 DataContract DataMember 装饰就足够了。无需 KnownType ServiceKnownType 装饰。

我们将使用它,并希望这样做没有陷阱。

概念证明

接口,DataContract和属性:

using System;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace ServiceTest
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        string TestMethod(ServiceDto dto);
    }

    [DataContract]
    public class ServiceDto
    {
        [DataMember]
        [DtoProperty(10)]
        public string DtoField { get; set; }
    }

    [DataContract]
    [AttributeUsage(AttributeTargets.Property)]
    public class DtoPropertyAttribute : Attribute
    {
        [DataMember]
        public int MaximumLength { get; set; }

        public DtoPropertyAttribute(int maximumLength)
        {
            MaximumLength = maximumLength;
        }   
    }
}

服务实施:

using System;

namespace ServiceTest
{
    public class Service : IService
    {
        public string TestMethod(ServiceDto dto)
        {
            if (dto == null)
                throw new ArgumentNullException("dto");

            var properties = typeof(ServiceDto).GetProperties();

            foreach (var property in properties)
            {
                var attributes = property.GetCustomAttributes(true);
                foreach (var attribute in attributes)
                {
                    var dtoPropAtt = attribute as DtoPropertyAttribute;
                    if (dtoPropAtt != null)
                    {
                        return string.Format("Maximum Length is: '{0}'!" ,dtoPropAtt.MaximumLength);
                    }
                }
            }

            return "Attribute Serialization Test Failed";
        }
    }
}

测试控制台应用程序,其服务引用指向Web服务主机(AttributeWcfTest)

using System;
using AttributeWcfTest.ServiceRef;

namespace AttributeWcfTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new ServiceRef.ServiceClient();
            var testDto = new ServiceDto()
            {
                DtoField = "Test Value"
            };

            var response = client.TestMethod(testDto);
            Console.WriteLine(response);
            Console.ReadLine();
        }
    }
}

<强>输出

enter image description here