C# 属性私有集;
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2366075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Properties private set;
提问by Eric
I know it only allows the class to set it, but what is the point?
我知道它只允许班级设置它,但有什么意义呢?
How do I solve the problem of having readonly ids?
如何解决只读 ID 的问题?
Say I have a person class:
假设我有一个 person 类:
public class Person
{
public string Name { get; set; }
public int Id { get; private set; }
public int Age { get; set; }
}
And this is in an Entities.dll
, used by a GUI, BL and DAL.
这是一个Entities.dll
, 由 GUI、BL 和 DAL 使用。
The GUI calls the BL:
GUI 调用 BL:
List<Person> p = BL.PeopleBL.GetPeople();
For the sake of the example calls the DAL:
为了示例调用 DAL:
...
while(dr.read())
{
returnPersonList.add( new Person{ Age=dr.GetInt32(1), Id=dr.GetInt32(0), Name=dr.GetString(2)})
}
...
of course I cannot do that cause Id is a private set; What is the proper way to do this?
当然我不能这样做,因为 Id 是一个私有集;这样做的正确方法是什么?
How can I let the BL/Dal set the Id, but not on the GUI?
我怎样才能让 BL/Dal 设置 Id,而不是在 GUI 上?
Or is this not even the proper use of a private set?
或者这甚至不是私人集的正确使用?
I just wanted to add that this is your typical DB app, where the pk is the Id and should not be changed( only by the BL/DAL)
我只想补充一点,这是您典型的 DB 应用程序,其中 pk 是 Id,不应更改(仅由 BL/DAL 更改)
采纳答案by BlitzKrieg
This is one possible solution although not very clean:
这是一种可能的解决方案,虽然不是很干净:
- Make the property you need to expose to BAL & DAL
internal
- Mark
BAL.dll
&DAL.dll
Internal Visibleinassemblyinfo.cs
- 使您需要向 BAL 和 DAL 公开的财产
internal
- 马克
BAL.dll
和DAL.dll
内部可见在assemblyinfo.cs
public class Person
{
public Person(int id)
{
this.Id=id;
}
public string Name { get; set; }
public int Id { get; internal set; }
public int Age { get; set; }
}
AssemblyInfo.cs
for Entities.dll
AssemblyInfo.cs
为了 Entities.dll
[assembly: InternalsVisibleTo("DAL"), InternalsVisibleTo("BAL")]
That way all your internals will be visible to DAL & BAL. This may not be desirable but I'm just suggesting one possible solution.
这样,您的所有内部结构都将对 DAL 和 BAL 可见。这可能是不可取的,但我只是建议一种可能的解决方案。
回答by Rex M
The two common approaches are either that the class should have a constructor for the DAL to use, or the DAL should use reflection to hydrate objects.
两种常见的方法是,类应该有一个构造函数供 DAL 使用,或者 DAL 应该使用反射来水合对象。
回答by John Saunders
while(dr.read())
{
returnPersonList.add(
new Person(dr.GetInt32(1), dr.GetInt32(0), dr.GetString(2)));
}
where:
在哪里:
public class Person
{
public Person(int age, int id, string name)
{
Age = age;
Id = id;
Name = name;
}
}
回答by Gregtheitroade
Or you can do
或者你可以做
public class Person
{
public Person(int id)
{
this.Id=id;
}
public string Name { get; set; }
public int Id { get; private set; }
public int Age { get; set; }
}
回答by Big Endian
Perhaps, you can have them marked as internal, and in this case only classes in your DAL or BL (assuming they are separate dlls) would be able to set it.
也许,您可以将它们标记为内部,在这种情况下,只有 DAL 或 BL 中的类(假设它们是单独的 dll)才能设置它。
You could also supply a constructor that takes the fields and then only exposes them as properties.
您还可以提供一个构造函数,该构造函数接受这些字段,然后仅将它们作为属性公开。
回答by Mark Seemann
You can let the user set a read-only property by providing it through the constructor:
您可以让用户通过构造函数提供它来设置只读属性:
public class Person
{
public Person(int id)
{
this.Id = id;
}
public string Name { get; set; }
public int Id { get; private set; }
public int Age { get; set; }
}
回答by Oded
This is normally the case then the ID is not a natural part of the entity, but a database artifact that needs be abstracted away.
通常是这种情况,那么 ID 不是实体的自然部分,而是需要抽象掉的数据库工件。
It is a design decision - to only allow setting the ID during construction or through method invocation, so it is managed internally by the class.
这是一个设计决策 - 只允许在构造期间或通过方法调用设置 ID,因此它由类内部管理。
You can write a setter yourself, assuming you have a backing field:
假设您有一个支持字段,您可以自己编写一个 setter:
private int Id = 0;
public void SetId (int id)
{
this.Id = id;
}
Or through a constructor:
或者通过构造函数:
private int Id = 0;
public Person (int id)
{
this.Id = id;
}
回答by Jacob G
Depending on the scope of my application, I like to put the object hydration mechanisms in the object itself. I'll wrap the data reader with a custom object and pass it a delegate that gets executed once the query returns. The delegate gets passed the DataReader. Then, since I'm in my smart business object, I can hydrate away with my private setters.
根据我的应用范围,我喜欢将对象水化机制放在对象本身中。我将使用自定义对象包装数据读取器,并将其传递给查询返回后执行的委托。委托通过 DataReader。然后,由于我在我的智能业务对象中,我可以用我的私人二传手来补充水分。
Edit for Pseudo-Code
编辑伪代码
The "DataAccessWrapper" wraps all of the connection and object lifecycle management for me. So, when I call "ExecuteDataReader," it creates the connection, with the passed proc (there's an overload for params,) executes it, executes the delegate and then cleans up after itself.
“DataAccessWrapper”为我包装了所有的连接和对象生命周期管理。因此,当我调用“ExecuteDataReader”时,它会创建连接,并使用传递的 proc(参数有重载)执行它,执行委托,然后自行清理。
public class User
{
public static List<User> GetAllUsers()
{
DataAccessWrapper daw = new DataAccessWrapper();
return (List<User>)(daw.ExecuteDataReader("MyProc", new ReaderDelegate(ReadList)));
}
protected static object ReadList(SQLDataReader dr)
{
List<User> retVal = new List<User>();
while(dr.Read())
{
User temp = new User();
temp.Prop1 = dr.GetString("Prop1");
temp.Prop2 = dr.GetInt("Prop2");
retVal.Add(temp);
}
return retVal;
}
}
回答by Robert Davis
Maybe I'm misunderstanding, but if you want truly readonly Ids why not use an actual readonly field?
也许我误解了,但是如果您想要真正的只读 ID,为什么不使用实际的只读字段呢?
public class Person
{
public Person(int id)
{
m_id = id;
}
readonly int m_id;
public int Id { get { return m_id; } }
}