如何在 C# 中通过反射迭代时跳过某些 class 字段?

How to skip some of the class fields while iterating by reflection in C#?

我有 classes 那些与 ASP.NET MVC 视图紧密绑定的。 针对他们的 fields/properties(列),我必须使用 Guid.NewGuid() 生成一个唯一的名称。这样,每次打开视图时,每个与 class.

内的特定 field/column 关联的控件都会有新的唯一名称

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

例如 class 是“

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; }
}

我怎样才能做到这一点?

一种可能的方法是定义您的自定义属性并忽略 属性(如果已分配)。

public sealed class SkipPropertyAttribute: Attribute
{  
}

在你的 class 上:

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 方法来查明属性是否已定义。

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

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

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

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;
    }
}

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

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;
        }
    }
}