【问题标题】:How to skip some of the class fields while iterating by reflection in C#?在 C# 中通过反射进行迭代时如何跳过某些类字段?
【发布时间】:2015-10-09 15:09:53
【问题描述】:

我有与 ASP.NET MVC 视图紧密绑定的类。 针对他们的字段/属性(列),我必须使用 Guid.NewGuid() 生成一个唯一的名称。这样,每次打开视图时,对于与该类中的特定字段/列关联的每个控件,都会有一个新的唯一名称。

但是,我想在生成唯一名称时跳过一些属性。因为,这些属性要么是隐藏的输入,要么是用于其他特定目的的占位符。什么是好方法?我应该为此应用自定义属性吗?在字段迭代期间,我会简单地跳过这些字段。

例如类是“

public abstract class DashboardModuleCommonSettings
{        
    public int ForwarderId { get; set; }
    public int ClientSubsidiaryId { get; set; }
    public bool IsContentUpdateable { get; set; }
    public int? AfterTime { get; set; }
    public string Title { get; set; }

    [Not Required to be iterated for generating unique name]
    public string ModuleSettingsPopupName { get; set; }

    [Not Required to be iterated for generating unique name]
    public int ClientId { get; set; }

    [Not Required to be iterated for generating unique name]
    [HiddenInput(DisplayValue = false)]
    public string CurrentLayout { get; set; }
}

我怎样才能做到这一点?

【问题讨论】:

  • 是的,自定义属性将是一个有效的解决方案。
  • 你能指导我在这种情况下如何实现吗?

标签: c# .net asp.net-mvc model-view-controller reflection


【解决方案1】:

这是一个完整的使用示例:

[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public class NotRequiredForUniqueNameAttribute : Attribute { }

NotRequiredForUniqueNameAttribute 应用于您不想使用的属性,因此您的类变为:

public abstract class DashboardModuleCommonSettings
{        
    public int ForwarderId { get; set; }
    public int ClientSubsidiaryId { get; set; }
    public bool IsContentUpdateable { get; set; }
    public int? AfterTime { get; set; }
    public string Title { get; set; }

    [NotRequiredForUniqueName]
    public string ModuleSettingsPopupName { get; set; }

    [NotRequiredForUniqueName]
    public int ClientId { get; set; }

    [NotRequiredForUniqueName]
    [HiddenInput(DisplayValue = false)]
    public string CurrentLayout { get; set; }
}

然后当你想提取不具有该属性的属性时,你可以这样做:

public class TestClass
{
    public static string GenerateUniqueName(DashboardModuleCommonSettings dmcs)
    {
        var propInfos = dmcs.GetType().GetProperties(
            BindingFlags.Instance | BindingFlags.Public).Where(
            p => p.GetCustomAttribute<NotRequiredForUniqueNameAttribute>() == null);

        string uniqueName = "";

        foreach (var propInfo in propInfos)
        {
            //Do something with the property info
        }

        return uniqueName;
    }
}

【讨论】:

    【解决方案2】:

    其中一种可能的方法是定义您的自定义属性并忽略已分配的属性。

    public sealed class SkipPropertyAttribute: Attribute
    {  
    }
    

    在你的课堂上:

    public abstract class DashboardModuleCommonSettings
    {        
        public int ForwarderId { get; set; }
        public int ClientSubsidiaryId { get; set; }
        public bool IsContentUpdateable { get; set; }
        public int? AfterTime { get; set; }
        public string Title { get; set; }
    
        [SkipProperty]
        public string ModuleSettingsPopupName { get; set; }
    
        [SkipProperty]
        public int ClientId { get; set; }
    
        [SkipProperty]
        [HiddenInput(DisplayValue = false)]
        public string CurrentLayout { get; set; }
    }
    

    您可以使用Attribute.IsDefined 方法来查看是否定义了属性。

    【讨论】:

    • Ivan :当然使用这种方法,我可以使用 Type.GetProperties(BindingFlags)。但是我应该使用哪个绑定标志? .NET 反射中是否有任何关于属性的绑定标志可用?
    • 所以Type.GetProperties(BindingFlags) 返回一个MemberInfo(是的,一个PropertyInfo一个MemberInfo),您可以将它作为参数提供给Attribute.IsDefined跨度>
    【解决方案3】:

    为了后代,这是没有标志的脏版本。

    public abstract class DashboardModuleCommonSettings
    {
        public int ForwarderId { get; set; }
        public int ClientSubsidiaryId { get; set; }
        public bool IsContentUpdateable { get; set; }
        public int? AfterTime { get; set; }
        public string Title { get; set; }
    
        public string __marker__ { get; }
    
        public string ModuleSettingsPopupName { get; set; }
        public int ClientId { get; set; }
        public string CurrentLayout { get; set; }
    }
    
    public static class Extractor
    {
        public static IEnumerable<PropertyInfo> VisibleProperties<T>()
        {
            foreach (var p in typeof(T).GetProperties())
            {
                if ("__marker__".Equals(p.Name, StringComparison.InvariantCultureIgnoreCase)) yield break;
                yield return p;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-01-14
      • 1970-01-01
      • 2012-07-08
      • 2011-01-13
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 2013-10-24
      • 2022-01-22
      相关资源
      最近更新 更多