我应该如何设计我的对象模型,以便我的DAL可以填充只读字段?

时间:2009-10-20 01:15:09

标签: c# .net asp.net

为了区分问题,在我当前的项目中,我决定在单独的程序集中完全分离我的DAL和BLL / Business对象。我希望将我的业务对象保持为简单的结构,而没有任何逻辑可以使事情变得非常简单。我想如果我可以将我的业务逻辑与我的DAL分开。所以我的应用程序将告诉我的DAL加载我的对象,我的DAL将运行到数据库并获取数据,用数据填充对象,然后将其传递回我的BLL。

问题 - 如何将DAL放在单独的程序集中并将数据推送到只读字段?

  • 如果我将getter设置为protected,那么继承的对象可以访问它,这不是我想要的,因为我将返回继承的对象类型,而不是原始的对象类型。
  • 如果我将getter设置为internal,那么我的DAL必须与我不想要的BLL位于同一个程序集中。
  • 如果我将getter设置为public,那么任何人只有在读取时才能读取/写入。

编辑:我注意到我可以有一个返回类型的ObjectBase,但实际上是返回一个对象或从ObjectBase派生的对象集合,所以对外界(在我的DAL之外)属性将是只读的,但我的派生类型(只能在我的DAL中访问)属性实际上是读/写。

5 个答案:

答案 0 :(得分:7)

您可以通过构造函数设置只读属性。

答案 1 :(得分:1)

这是没有银弹的情况;最简单的选择是有限的或不符合您的要求,彻底的解决方案要么开始有气味,要么开始偏离简单。

也许最简单的选项是我在这里没有提到过的选项:保持字段/属性为私有,并将它们作为out / ByRef参数传递给DAL。虽然它对大量字段不起作用,但对于少数字段来说很简单。

(我没有测试过,但我觉得值得探讨)。

public class MyObject()
{
    private int _Id;
    public int Id { get { return _Id; } } // Read-only

    public string Name { get; set; }

    // This method is essentially a more descriptive constructor, using the repository pattern for seperation of Domain and Persistance
    public static MyObject GetObjectFromRepo(IRepository repo)
    {
        MyObject result = new MyObject();
        return repo.BuildObject(result, out _Id);            
    }
}

public class MyRepo : IRepository
{
    public MyObject BuildObject(MyObject objectShell, out int id)
    {
        string objectName;
        int objectId;

        // Retrieve the Name and Value properties
        objectName = "Name from Database";
        objectId = 42;
        //

        objectShell.Name = objectName;
        Console.WriteLine(objectShell.Id); // <-- 0, as it hasn't been set yet
        id = objectId; // Setting this out parameter indirectly updates the value in the resulting object
        Console.WriteLine(objectShell.Id); // <-- Should now be 42
    }
}

值得注意的是,尝试将域/业务对象保持在最低限度可能比您想象的要多。如果您打算对它们进行数据绑定,那么您将需要实现IPropertyNotifyChanged,这会阻止您使用自动实现的属性。您应该能够保持相当干净,但您必须为基本功能做出一些牺牲。

答案 2 :(得分:1)

这样可以很好地保存您的SoC模型,它不会增加太多的复杂性,它会阻止写入只读字段,您可以使用非常相似的模型来处理序列化问题。您的只读字段仍然可以由您的DAL写入,如果以类似的方式使用,您的序列化程序也可以写入 - 这意味着开发人员必须有意识地努力写入只读字段,以防止意外滥用。 / p>

模型项目

namespace Model
{
    public class DataObject
    {
        public int id { get; protected set; }
        public string name { get; set; }
    }   
}

数据项目

namespace Data
{
    class DALDataObject : DataObject
    {
        public DALDataObject(int id, string name)
        {
            this.id = id;
            this.name = name;
        }
    }
    public class Connector
    {
        public static DataObject LoadDataObject(int objectId)
        {
            return new DALDataObject(objectId, string.Format("Dummy object {0}", objectId));
        }
        public static IEnumerable<DataObject> LoadDataObjects(int startRange, int endRange)
        {
            var list = new List<DataObject>();
            for (var i = startRange; i < endRange; i++)
                list.Add(new DALDataObject(i, string.Format("Dummy object {0}", i)));

            return list;
        }
    }
}

答案 3 :(得分:0)

与它一起生活怎么样?

使用这些指南实施,但不要在模型中添加这样的硬约束。让我们说你这样做,但接下来需要序列化或做其他事情的另一个req,然后你就与它绑在一起。

正如你在其他评论中所说,你想要的是可互换的部分......所以,基本上你不需要与特定关系相关的东西。


更新1:或许“只是忍受它”太简单了,但我仍然要强调你不应该深入研究这些事情。使用简单的指导原则,保持代码清洁,并在开始时尽力使用SOLID。当一切都更加稳定时,重构不会妨碍进步。

毫无疑问,我根本不是一个没有任何思考就编写代码的人。但是,我已经采用了这样的方法,并且只有在少数情况下才会付出代价 - 没有任何迹象表明你不会通过简单和不断发展来获得类似的结果。

恕我直言,这个问题不适合需要在一开始就解决的重要架构问题。

先发制人的跟进:请注意,如果您不相信您的团队遵循简单的指导原则。还要确保从一些结构开始,选择一些场景,用真实的东西设置结构,当有简单时,团队会更好地了解他们的方式。

答案 4 :(得分:0)

在我看来,处理此问题的最佳方法是将业务对象和DAL放在由命名空间分隔的同一程序集中。这在逻辑上区分了这些问题,并允许您使用内部设置器。我想不出将它们分成自己的集合会有什么好处,因为没有另一个集合就没用了。