C#自动属性 ​​- 是否可以使用默认的setter自定义getter?

时间:2010-09-23 00:36:22

标签: c#

我有可能首先尝试这个,但这是我到目前为止所做的:

public List<int> AuthorIDs
{
    get
    {
        var l = new List<int>();
        using (var context = new GarbageEntities())
        {
            foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == this.BookID)).ToList())
            {
                l.Add(author.AuthorID);
            }
        }
        return l;
    }
    set; //compiler error
}

如果没有任何自定义逻辑,我将如何离开上面的setter?在过去,我认为你只会使用:

set { authorIDs = value; }

现在不起作用。

这个想法一开始就很糟糕吗?

修改

回答一些人的问题:我正在尝试将MVC与Data Annotation验证结合使用默认绑定,与Entity Framework 4.0相结合......并且我相信它失败了。

5 个答案:

答案 0 :(得分:7)

不,这是不可能的。要么一切都是明确的,要么整个属性都是自动的。无论如何,在这种情况下,设定者似乎没有任何意义......根本就没有设定者。

另外,我认为你应该把它变成一种方法。这将使调用者更清楚它执行可能的长度计算。它也违反了在财产中执行复杂处理的准则。

答案 1 :(得分:4)

这个答案比简单地摆脱属性上的setter要宽一些 - 将它与其余的答案和注释结合起来,并取出有意义的位。希望最后的一点也有帮助,也许现在不行。

如果您在模型中使用它来进行数据绑定,因此希望将其作为属性公开,我会这样做:

public class BookModel
{
    public IList<int> AuthorIds { get; set; }
}

创建一个服务,您将调用该服务来填充您的模型:

public class BookService()
{
    public List<int> GetAuthorIDs(int bookId)
    {
        var authorIds = new List<int>();
        using (var context = new GarbageEntities())
        {
            foreach (var author in context.Authors.Where(
                a => a.Books.Any(b => b.BookID == bookId)))
            {
                authorIds.Add(author.AuthorID);
            }
        }
        return authorIds;
    }
}

在您的控制器中:

public ViewResult List(int id)
{
    var model = new BookModel 
    {
        AuthorIds = service.GetAuthorIDs(id)
    };

    return View(model);
}

我明确没有包括如何在控制器中实例化book服务。我的偏好是在运行时在构造函数中注入它,但这需要你有一个自定义控制器工厂 - 一次一个步骤。您可以在默认构造函数中新建它:

private readonly BookService service; 

public BookController()
{
    service = new BookService();
}

在一个理想的世界里,我会这样做:

private readonly BookService service; 

public BookController(BookService service)
{
    if(service == null)
        throw new ArgumentException("service must be supplied");

    this.service = service;
}

然而,默认的MVC控制器工厂期望控制器具有默认参数,因此使用构造函数注入执行此操作将需要更多的工作。

答案 2 :(得分:3)

默认的setter将在编译时创建一个支持变量,其名称如下:

[CompilerGenerated]
private string <AuthorIDs>k__BackingField;

由于这是在编译时创建的,因此在创建代码之前不能在代码中引用它,此外,在变量名中不允许使用尖括号(有意)。

由于这个原因,允许将某些内容存储在此变量中(这实际上就是自动setter所做的事情)是无用的,并且无法在将来的任何时候访问此值(在所有getter之后)这里不是一个自动获取器,它会返回完全不同的东西)

所以对于没有getter的summerise,会有(这是从这个支持变量中检索值的唯一方法),拥有私有的setter是没有意义的

答案 3 :(得分:2)

如果您想按照自己的方式行事,请执行以下操作:

private List<int> authorIDs;
public List<int> AuthorIDs
{
    get
    {
        var l = new List<int>();
        using (var context = new GarbageEntities())
        {
            foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == this.BookID)).ToList())
            {
                l.Add(author.AuthorID);
            }
        }
        return l;
    }

    set{authorIDs = value; //this does not make much sense though ... what are you trying to do by setting authorIDs?
}
}

但就像其他人说的那样,这对于一个属性来说太过分了,把它放在方法中,比如

public List<int> GetAuthorIDs(int bookId)
    {
            var l = new List<int>();
            using (var context = new GarbageEntities())
            {
                foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == bookId)).ToList())
                {
                    l.Add(author.AuthorID);
                }
            }
            return l;
        }

答案 4 :(得分:0)

实际上有一种方法可以做到这一点:

public List<int> AuthorIDs
{
    get
    {
        var l = new List<int>();
        using (var context = new GarbageEntities())
        {
            foreach (var author in context.Authors.Where(a => a.Books.Any(b => b.BookID == this.BookID)).ToList())
            {
                l.Add(author.AuthorID);
            }
        }
        return l;
    }
    set{
       this.SetPropertyValue(page => page.AuthorIDs, value);
    }
}
相关问题