【问题标题】:Getting the name of all DataMembers in a DataContract获取 DataContract 中所有 DataMember 的名称
【发布时间】:2011-11-16 13:14:33
【问题描述】:

我正在使用 WCF 服务

我有一份数据合同:

[DataContract]
[KnownType(typeof(CustomBranches))]
public class CustomBranches
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string branch_name { get; set; }

    [DataMember]
    public string address_line_1 { get; set; }

    [DataMember]
    public string city_name { get; set; }
}

我是否可以在这个类中找到所有 DataMember 的名称 CustomBranches

如“ID”、“分行名称”等

谢谢

【问题讨论】:

    标签: c# asp.net wcf


    【解决方案1】:

    你需要做什么:

    • 您不需要在CustomBranches 类中添加[KnownType(typeof(CustomBranches))]。一个类总是知道自己。
    • 您需要过滤属性以仅获取具有[DataMember] 属性的属性(nillls 的代码全部返回)
    • 数据成员属性也可以是非公开的(如果序列化以完全信任的方式运行,它就可以工作)
    • 数据成员也可以是字段(不仅是属性),因此您也需要考虑它们。

    这是一个执行所有这些的代码示例。

    public class StackOverflow_8152252
    {
        public static void Test()
        {
            BindingFlags instancePublicAndNot = BindingFlags.Instance |
                BindingFlags.Public |
                BindingFlags.NonPublic;
            var memberNames = typeof(CustomBranches)
                .GetProperties(instancePublicAndNot)
                .OfType<MemberInfo>()
                .Union(typeof(CustomBranches).GetFields(instancePublicAndNot))
                .Where(x => Attribute.IsDefined(x, typeof(DataMemberAttribute)))
                .Select(x => x.Name);
            Console.WriteLine("All data member names");
            foreach (var memberName in memberNames)
            {
                Console.WriteLine("  {0}", memberName);
            }
        }
    
        [DataContract]
        public class CustomBranches
        {
            [DataMember]
            public int Id { get; set; }
    
            [DataMember]
            public string branch_name { get; set; }
    
            [DataMember]
            public string address_line_1 { get; set; }
    
            [DataMember]
            public string city_name { get; set; }
    
            public int NonDataMember { get; set; }
    
            [DataMember]
            public string FieldDataMember;
    
            [DataMember]
            internal string NonPublicMember { get; set; }
        }
    }
    

    【讨论】:

    • 请注意,一个类型的祖先,如果有的话,每个都有自己的DataContract 属性。因此,对于过滤属性和字段,您可能需要包含 DeclaredOnly 绑定标志。在这种情况下,也将inherit: false 传递给IsDefined
    【解决方案2】:

    鉴于它是一个数据合同,您很可能应该拥有所有这些属性,但如果没有,以下应该列出您类型的所有属性:

    Type T =(typeof(T));
    var properties = T.GetProperties(BindingFlags.Public|BindingFlags.Instance);
    

    将 T 替换为类型,一切顺利。根据您的需要,您可能需要不同的BindingFlags

    【讨论】:

    • 类型 typ = (typeof(T)); T 不能既是类型又是 Type 变量名。 T 也应该为泛型中的泛型类型保留。无论如何感谢您的提示。
    【解决方案3】:

    我稍微修改了 Carlos 的回答,以忽略用 [NonSerialized] 属性装饰的数据成员:

    public class StackOverflow_8152252
    {
        public static void Test()
        {
            BindingFlags instancePublicAndNot = BindingFlags.Instance |
                BindingFlags.Public |
                BindingFlags.NonPublic;
            var memberNames = typeof(CustomBranches)
                .GetProperties(instancePublicAndNot)
                .OfType<MemberInfo>()
                .Union(typeof(CustomBranches).GetFields(instancePublicAndNot))
                .Where(x => Attribute.IsDefined(x, typeof(DataMemberAttribute))
                         && !Attribute.IsDefined(x, typeof(NonSerializedAttribute)))
                .Select(x => x.Name);
            Console.WriteLine("All data member names");
            foreach (var memberName in memberNames)
            {
                Console.WriteLine("  {0}", memberName);
            }
        }
    
        [DataContract]
        public class CustomBranches
        {
            [DataMember]
            public int Id { get; set; }
    
            [DataMember]
            [NonSerialized]
            public string NonSerializedDataMember { get; set; }
        }
    }
    

    【讨论】:

      【解决方案4】:

      在我的例子中,我有几个自定义数据成员名称的属性,定义如下:

      [DataMember(Name = "alternate_name")]

      我已修改 mbonness 的答案,以在存在时返回自定义名称,否则返回默认属性名称。

      public class StackOverflow_8152253
      {
          public static void Test()
          {
              BindingFlags instancePublicAndNot = BindingFlags.Instance |
                  BindingFlags.Public |
                  BindingFlags.NonPublic;
              var memberNames = typeof(CustomBranches)
                  .GetProperties(instancePublicAndNot)
                  .OfType<MemberInfo>()
                  .Union(typeof(CustomBranches).GetFields(instancePublicAndNot))
                  .Where(x => Attribute.IsDefined(x, typeof(DataMemberAttribute))
                           && !Attribute.IsDefined(x, typeof(NonSerializedAttribute)))
                  .Select(x => x.CustomAttributes.FirstOrDefault(a => a.AttributeType == typeof(DataMemberAttribute))?.NamedArguments.FirstOrDefault(n => n.MemberName == "Name").TypedValue.Value ?? x.Name);
              Console.WriteLine("All data member names");
              foreach (var memberName in memberNames)
              {
                  Console.WriteLine("  {0}", memberName);
              }
          }
      
          [DataContract]
          public class CustomBranches
          {
              [DataMember]
              public int Id { get; set; }
      
              [DataMember(Name = "alternate_name")]
              public string PropertyWithAlternateName { get; set; }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-01-20
        • 1970-01-01
        • 1970-01-01
        • 2012-01-23
        • 1970-01-01
        • 2016-02-18
        • 1970-01-01
        • 2011-08-03
        • 2016-11-04
        相关资源
        最近更新 更多