c# – 使用反射和锁定正确地实例化分配给私有静态volatile变量的类
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 使用反射和锁定正确地实例化分配给私有静态volatile变量的类,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3474字,纯文字阅读大概需要5分钟。
内容图文
![c# – 使用反射和锁定正确地实例化分配给私有静态volatile变量的类](/upload/InfoBanner/zyjiaocheng/769/18d1652c22414c46b1da8685c709df99.jpg)
所以这是一个我想要改进或确认的人为例子.
我正在使用(我/我)BATIS.NET(一个轻量级的ORM /数据映射器框架),我所拥有的是一个类,它为数据库的每个表映射器提供静态引用.它工作得很好,但有很多重复,我认为可能有机会大大简化代码.该类目前看起来像这样:
public sealed class MyRepository
{
private static string _connectionString;
private volatile static TableAbcMapper _tableAbcMapper;
private volatile static TableXyzMapper _tableXyzMapper;
// and about 30 more of these
private MyRepository()
{
}
public static void Init(string connectionString)
{
_connectionString = connectionString;
}
public static string ConnectionString
{
get { return _connectionString; }
}
public static TableAbcMapper TableAbc
{
get
{
if (_tableAbcMapper == null)
{
lock (typeof(TableAbcMapper))
{
if (_tableAbcMapper == null)
{
_tableAbcMapper = new TableAbcMapper(_connectionString);
}
}
}
return _tableAbcMapper;
}
}
public static TableXyzMapper TableXyz
{
get
{
if (_tableXyzMapper == null)
{
lock (typeof(TableXyzMapper))
{
if (_tableXyzMapper == null)
{
_tableXyzMapper = new TableXyzMapper(_connectionString);
}
}
}
return _tableXyzMapper;
}
}
// and about 30 more of these readonly properties
}
每次我向数据库添加或删除一个表时,我都会向MyRepository类添加一个私有的volatile静态字段和那个丑陋的singleton-y属性.我的第一个想法是让属性在类中调用泛型实例函数;看起来像这样的东西:
private static void InitMapper<TMapper>(TMapper instance) where TMapper : MyMapper
{
lock (typeof(TMapper))
{
if (instance == null)
{
instance = Activator.CreateInstance(typeof(TMapper),
new object[] { _connectionString }) as TMapper;
}
}
}
然后公众的吸气者可以略微减少到:
public static TableXyzMapper TableXyz
{
get
{
if (_tableXyzMapper == null)
{
InitMapper<TableXyzMapper>(_tableXyzMapper);
}
return _tableXyzMapper;
}
}
但是,我不知道在volatile字段周围传递是否是一个好主意,并且使用ref或out with volatile字段是禁止的,并且最重要的是它不会减少所有那么多的代码量.
我想要做的是完全重构MyRepository类,使其没有私有字段,也没有公共getter,并使用反射来立即初始化所有映射器而不是延迟加载它们.我不必更改任何使用MyRepository类的代码,因为它看起来完全一样,但是它会有点不同:
public sealed class MyRepository
{
private MyRepository()
{
}
public volatile static TableAbcMapper TableAbc = null;
public volatile static TableXyzMapper TableXyz = null;
public static void Init(string connectionString)
{
foreach (var fieldInfo in typeof(MyRepository).GetFields(BindingFlags.Static))
{
if (fieldInfo.GetValue(new MyRepository()) == null)
{
lock (fieldInfo.FieldType)
{
if (fieldInfo.GetValue(new MyRepository()) == null)
{
fieldInfo.SetValue(new MyRepository(),
fieldInfo.FieldType.GetConstructor(new Type[] { typeof(string) })
.Invoke(new object[] { connectionString }));
}
}
}
}
}
}
现在,当新表添加到数据库时,我必须做的唯一维护就是为它添加一个新的公共易失性静态字段,反射将处理其余部分.
我对这种方法有几个问题:
>这种方法在功能上与原始类相同吗?
>使用反射定义volatile变量是否有任何危险?
>它是否与原始类一样可读(假设它已全部注释)?
最后,如果这是一个更适合Code Review网站的问题,我就是为了让它迁移(mods!).
解决方法:
它可能不会短得多,但由于你已经有了一个init方法,你可以创建一个在第一次访问时创建的惰性值.关于Lazy(.NET 4的一部分)的好处是你可以指定值可以创建多次,但是它的值只发布一次(给出更好的性能).
class Program
{
static Lazy<string> _Lazy;
static string _connectionString;
public string LazyValue
{
get
{
return _Lazy.Value;
}
}
public static void Init(string connectionString)
{
_connectionString = connectionString;
_Lazy = new Lazy<string>(() => new string(connectionString.ToArray()), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
}
但它不会变短.
内容总结
以上是互联网集市为您收集整理的c# – 使用反射和锁定正确地实例化分配给私有静态volatile变量的类全部内容,希望文章能够帮你解决c# – 使用反射和锁定正确地实例化分配给私有静态volatile变量的类所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。