假设我有以下C#类,我希望它是不可变的。您只能使用参数化构造函数来设置它。
public class InsulineInjection
{
private InsulineInjection()
{
// We don't want to enable a default constructor.
}
public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
{
this.Remark = remark;
this.DateTime = dateTime;
this.Millilitre = millilitre;
}
public string Remark { get; private set; }
public DateTime DateTime { get; private set; }
public Millilitre Millilitre { get; private set; }
}
现在我想使用ORM来创建这个POCO。但是,据我所知,所有.NET ORM都希望可以访问属性,并且有一个公共构造函数可以创建这个POCO。所以我必须将我的POCO改为:
public class InsulineInjection
{
public InsulineInjection()
{
}
public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
{
this.Remark = remark;
this.DateTime = dateTime;
this.Millilitre = millilitre;
}
public string Remark { get; set; }
public DateTime DateTime { get; set; }
public Millilitre Millilitre { get; set; }
}
然而,这使我的POCO再次变得可变。使用它的人可以随后改变任何不属于我想要的属性。
据我所知,我可以通过两种不同的方式解决这个问题:
我倾向于解决方案2.有人有一个如何做到这一点的例子吗?或者有人有比我上面描述的解决方案更好的解决方案吗?
答案 0 :(得分:5)
只要有默认构造函数和setter(无论它们是否公开,它们只需要存在),许多OR / Ms都会工作。
所以这不会工作(没有默认构造函数):
public class InsulineInjection
{
public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
{
this.Remark = remark;
this.DateTime = dateTime;
_millilitre = millilitre;
}
public string Remark { get; set; }
public DateTime DateTime { get; set; }
public Millilitre Millilitre { get { return _millilitre; } }
}
或者这个(没有最后一个属性的setter)
public class InsulineInjection
{
public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
{
this.Remark = remark;
this.DateTime = dateTime;
_millilitre = millilitre;
}
public string Remark { get; set; }
public DateTime DateTime { get; set; }
public Millilitre Millilitre { get { return _millilitre; } }
}
虽然这样可行:
public class InsulineInjection
{
protected InsulineInjection()
{
// works with many OR/Ms
}
public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark)
{
this.Remark = remark;
this.DateTime = dateTime;
this.Millilitre = millilitre;
}
public string Remark { get; private set; }
public DateTime DateTime { get; private set; }
public Millilitre Millilitre { get; private set; }
}
答案 1 :(得分:3)
为避免您自己的代码使用构造函数,您可以使用Obsolete attribute
[Obsolete("Default constructor only here for the ORM", true)]
public InsulineInjection() {}
如果您实际调用此构造函数,则在属性中传递true
将产生编译器错误。
答案 2 :(得分:2)
并非所有.NET ORM都需要公共属性访问才能写入数据。 NHibernate支持将数据写入私有字段或setter。但是,您需要遵循一个允许的字段命名约定,以便它可以从属性名称中推断出字段名称。
Check out NHibernate documentation about property mapping,特别是看表5.1。访问策略和表5.2。命名策略。查看nosetter
访问策略并选择符合您编码风格的命名策略。
答案 3 :(得分:1)
此方案由dapper-dot-net原生处理。
您只需要查询字段的顺序和类型以匹配构造函数参数的顺序和类型。因此,对于您的类,查询将类似于:
select millilitre,
,dateTime
,remark
from injections
不幸的是,dapper不知道如何将某些东西从十进制转换为毫升。