.net 检查模型中的所有字段是否为null c#

amrnrhlw  于 2023-08-08  发布在  .NET
关注(0)|答案(3)|浏览(160)

下面是模型。将来,字段的数量可能会增加。我想知道我怎么可能检查一个模型的所有字段都为空。在.net核心c#

public class model
{
    public string Duration { get; set; }
    public TimeSpan? TimeZoneOffset { get; set; }
    public TimeOnly? RolloverTime { get; set; }
    public bool? IncludeCurrent { get; set; }
}

字符集

rsaldnfx

rsaldnfx1#

以下是我作为评论提出的三个选择。

首先:* 在模型类上创建一个方法来完成工作。*

这是最简单的方式(当然,最简单的思考)。缺点是它需要在每个模型类上工作,更重要的是,维护起来可能很麻烦(因为对模型的每次更新都需要对方法进行更新)。
有一点要注意,它必须总是执行最快的。
像@RolanShun一样,我选择创建一个接口来描述遵循此行为的模型(不值得在此浪费模型的一个可能的基类,因为实现之间没有公共行为)
接口:

public interface INullPropertiesCheckable
{
    bool AreAllPropertiesNull();
}

字符集
以及一种实现:

public class MyModel : INullPropertiesCheckable
{
    public string? Duration { get; set; }
    public TimeSpan? TimeZoneOffset { get; set; }
    public TimeOnly? RolloverTime { get; set; }
    public bool? IncludeCurrent { get; set; }

    public bool AreAllPropertiesNull()
    {
        return
            (Duration == null &&
             !TimeZoneOffset.HasValue &&
             !RolloverTime.HasValue &&
             !IncludeCurrent.HasValue);
    }
}

*第二: 使用直上反射 *

这将是最慢的执行方式(因为您在类型上进行反射,获取属性getter并在每次调用时调用它们)。然而,它易于理解,易于编写,并且不需要每个模型编码:

public static bool CheckAllPropertiesAreNull<T>(T obj) 
{
    var readableProps = typeof(T).GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).Where(p => p.CanRead);
    foreach (var prop in readableProps)
    {
        if (prop.GetValue(obj) != null)
        {
            return false;
        }
    }
    return true;
}

*第三: 使用Reflection,但创建并缓存reflection worker *

如果你要经常这样做,并且经常调用这个方法,这可能是一条路。它对每个类型执行一次反射重载(反射类型并发现属性getter),并缓存结果。每次调用只是提取正确的worker(从键入类型的字典中),并快速调用所有属性getter。
我经常使用这种模式。

public class ArePropsNullWorker
{
    // access to the (static) cached ArePropsNullWorker instances
    private static Dictionary<Type, ArePropsNullWorker> workerCache = new Dictionary<Type, ArePropsNullWorker>();
    private static object workerLock = new object();

    // The List and the constructor are private, and are per-instance
    private List<MethodInfo> propertyReaders = new List<MethodInfo>();

    private ArePropsNullWorker(Type type)
    {
        var readableProps = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).Where(p => p.CanRead);
        foreach (var prop in readableProps)
        {
            var propertyReader = prop.GetGetMethod();
            if (propertyReader != null)     //should never be null, but the compiler doesn't know that
            {
                propertyReaders.Add(propertyReader);
            }
        }
    }

    public static bool CheckAllPropertiesAreNull<T>(T obj)
    {
        ArePropsNullWorker? worker;
        lock (workerLock)
        {
            if (!workerCache.TryGetValue(typeof(T), out worker))
            {
                worker = new ArePropsNullWorker(typeof(T));
                workerCache.Add(typeof(T), worker);
            }
            // at this point, worker will point to a valid, non-null ArePropsNullWorker
        }
        foreach (var propertyReader in worker.propertyReaders)
        {
            object? propertyValue = propertyReader.Invoke(obj, null);
            if (propertyValue != null)
            {
                return false;
            }
        }
        return true;

    }
}


查看代码,您可以看到静态ArePropsNullWorker.CheckAllPropertiesAreNull<T>(T obj)提供了对它的访问。
对类的唯一示例构造函数的访问是private,所有示例都在类的静态成员中进行管理。因为我猜你打算在web应用程序中使用它,所以我添加了一个lock来允许多线程访问。

4bbkushb

4bbkushb2#

您可以编写一个扩展方法或一些辅助方法来检查是否有任何字段为NULL并返回布尔标志。

void Main()
{
        var m = new model() { Duration = "abc", IncludeCurrent = true};
         CheckIfAnyPropertyNull(m).Dump();
}

public static bool CheckIfAnyPropertyNull(model m)
{
        PropertyInfo[] properties = typeof(model).GetProperties();
        foreach (PropertyInfo property in properties)
        {
            if(property.GetValue(m) == null)
                return true;
        }
        
        return false;
}

public class model
{
    public string Duration { get; set; }
    public TimeSpan? TimeZoneOffset { get; set; }
    public TimeSpan? RolloverTime { get; set; }
    public bool? IncludeCurrent { get; set; }
}

字符集

0lvr5msh

0lvr5msh3#

//Implement interface on any class that need this null check
public interface iVerifyNull
{
    bool CheckIfAnyPropertyNull();
}

public class model: iVerifyNull
{
    public string Duration { get; set; }
    public TimeSpan? TimeZoneOffset { get; set; }
    public TimeOnly? RolloverTime { get; set; }
    public bool? IncludeCurrent { get; set; }

    public bool CheckIfAnyPropertyNull()
    {
        PropertyInfo[] properties = typeof(model).GetProperties();
        foreach (PropertyInfo property in properties)
        {
            if (property.GetValue(this) == null)
                return true;
        }

        return false;
    }
}

//Usage
model model1 = new model(){ Duration = "abc", IncludeCurrent = null};;
if (model1.CheckIfAnyPropertyNull())
{
     //Null value found, do what you need to do here...
}

字符集

相关问题