对多个getter执行的通用操作

本文关键字:操作 执行 getter | 更新日期: 2023-09-27 18:15:00

我试图找到一种简洁的方法来触发加载机制,当几个getter中的一个被首次访问。我的第一个想法是这样的:

public class Customer {
    private bool loaded = false;
    public int PK { get; set; }
    public string Email { get; set; }
    public string Name { get { if (!loaded) loadData(); return _name; } set { ... } }
    public string Street { get { if (!loaded) loadData(); return _street; } set { ... } }
    public string City { get { if (!loaded) loadData(); return _city; } set { ... } }
}

简而言之,在本例中,每个Customer都存在其基础数据PKEmail,直到其中一个属性被访问。

这将意味着大量的重复代码,随着类的复杂性而增加。是否有办法为这些属性创建某种继承?

类似这样,但我认为这是不可能的:

private void checkData() { if (!loaded) loadData(); }
public string Name:checkData { get; set; }
public string Street:checkData { get; set; }
public string City:checkData { get; set; }

另一种方法可能是通过反射,但由于我没有经验,我不知道从哪里开始。

任何提示都非常感谢!: -)

对多个getter执行的通用操作

您可以使用Lazy<T>类来包装次要属性。这样,loadData只会在任何辅助getter被调用时执行,并且不会执行超过一次。

    public class Customer
    {
        public int PK { get; set; }
        public string Email { get; set; }
        public string Name { get { return data.Value.Name; } }
        public string Street { get { return data.Value.Street; } }
        public string City { get { return data.Value.City; } }
        public Customer()
        {
            data = new Lazy<CustomerData>(loadData);
        }

        private CustomerData loadData()
        {
            ...
        }
        private struct CustomerData
        {
            public string Name, Street, City;
        }
        private Lazy<CustomerData> data;
    }

还有一种不那么美丽的方式。您可以编写一个包装泛型方法,这样可以减少属性内的代码。

下面是一个例子:

public string Name
{
    get { return Get(m_name); }
    set { m_name = value; }
}
public static T Get<T>(T value)
{
    if (!loaded)
    {
        loadData();
    } 
    return value;
}

请注意,这将降低性能,因为您的属性将始终调用一个额外的方法。您可以尝试强制编译器内联该方法(如果还没有发生的话)。