What came before

In my previous post I discussed ways of making the settings table using Generics to have typed access to our properties. This required us to still pass in the name of our property as a string to a method.

User user = db.Users.First();if(user.Setting<bool>("IsAdministrator")){//yay, this user is an admin!}

Today we’re going to take advantage of dynamic to take it one step further.

The Goal

User user = db.Users.First();if(user.Settings.IsAdministrator){//yay, this user is an admin!}

We’re going to create a new class that inherits from DynamicObject. Doing so will allow us to utilize all the power of dynamics such as getting/setting members, calling methods, or type conversions. <a

The dynamic language runtime first checks to see if the property of our DynamicObject already exists and if it doesn’t find the property it calls TryGetMember or TrySetMember. This is what we’re going to use to return our settings property. Here is a barebones DynamicObject that uses aDictionary<string, object> to store values.

//These are essentially the same//user.Settings["IsAdministrator"]//user.Settings.IsAdministratorclassSettingsDynamicObject:DynamicObject{//used for cachingDictionary<string,object> _dictionary;publicSettingsDynamicObject(User user){
_dictionary =newDictionary<string,object>();}publicoverrideboolTrySetMember(SetMemberBinder binder,object value){
_dictionary[binder.Name]= value;returntrue;}publicoverrideboolTryGetMember(GetMemberBinder binder,outobject result){if( _dictionary.TryGetValue(binder.Name,out result)){returntrue;}}}

Adding our new database overrides

We’re now going to modify our overrides to pull values from the database if they don’t already exist in the _dictionary object and add our code to save the new values.

publicoverrideboolTrySetMember(SetMemberBinder binder,object value){SetDatabaseValue(binder.Name, value);
_dictionary[binder.Name]= value;returntrue;}publicoverrideboolTryGetMember(GetMemberBinder binder,outobject result){//check to see if the property already existsif( _dictionary.ContainsKey(binder.Name)&& _dictionary.TryGetValue(binder.Name,out result)){returntrue;}else{var setting =this.user
.UserSettings.SingleOrDefault(s => s.Name== binder.Name);if(setting ==null){
result =null;}else{
result =newBinaryFormatter().Deserialize(newSystem.IO.MemoryStream(setting.Value));
_dictionary[binder.Name]= result;}returntrue;}}privatevoidSetDatabaseValue(string name,object value){var setting =this.user.UserSettings.SingleOrDefault(s => s.Name== name);System.IO.MemoryStream ms =newSystem.IO.MemoryStream();newBinaryFormatter().Serialize(ms, value);if(setting ==null){
setting =newUserSetting(){Name= name,Type= value.GetType().ToString(),
setting.Value= ms.ToArray();this.user.UserSettings.Add(setting);}else{if(value !=null&& setting.Type!= value.GetType().FullName)thrownewInvalidCastException(string.Format("Unable to cast: {0} to {1}",
value.GetType().FullName, setting.Type));
setting.Value= ms.ToArray();}}

Modifying our existing user object

Now we have a new DynamicObject class that we can use to populate our settings but we’ll need to modify our existing User class to utilize the new Settings. One of the downsides is that we’ll have two exposed properties instead of one but I think it’s negligable.

publicclassUser{publicInt32UserID{get;set;}publicstringLoginID{get;set;}publicstringName{get;set;}publicstringPage{get;set;}publicstringPassword{get;set;}publicvirtualICollection<UserSetting>UserSettings{get;set;}publicvirtualdynamicSettings{get;set;}publicUser(){//We need to initialize the Settings to our new DynamicObjectSettings=newSettingsDynamicObject(this);}}

And there you have it. We now have a dynamic enabled settings property that makes our code slightly easier to read. I hope this helps you on your way to understanding c# 4.0’s new dynamic namespace.

– Ben

Update:

Fixed Constructor – thanks yesthatmcgurk

http://buildstarted.com/2010/08/23/fun-with-dynamicobject-dynamic-and-the-settings-table/

Fun with dynamicobject dynamic and the settings table的更多相关文章

  1. Creating a settings table that can handle almost any type of value

    Update: Updated article here. Today I wanted to be able to have a table store any type of value as a ...

  2. 【原创】大叔问题定位分享(22)hive同时执行多个insert overwrite table只有1个可以执行

    hive 2.1 一 问题 最近有一个场景,要向一个表的多个分区写数据,为了缩短执行时间,采用并发的方式,多个sql同时执行,分别写不同的分区,同时开启动态分区: set hive.exec.dyna ...

  3. CSharp 案例:用 Dynamic 来解决 DataTable 数值累加问题

    需求说明 给定一个 DataTable,如果从中取出数值类型列的值并对其累加? 限制:不知该列是何种数值类型. 解决方案 1.将表转换为 IEnumerable<dynamic>,而后获取 ...

  4. [转]Dynamic SQL & Stored Procedure Usage in T-SQL

    转自:http://www.sqlusa.com/bestpractices/training/scripts/dynamicsql/ Dynamic SQL & Stored Procedu ...

  5. DataTable转List<dynamic>

    DataTable转List<dynamic> 最近做的一个项目,MVC+Ado.net.没有ORM很不习惯.找到一个办法,DataTable转List<dynamic>,这样 ...

  6. Dynamic view

    Views are a useful feature of SQL databases, letting us create virtual tables based on SQL select st ...

  7. Working with the Dynamic Type in C#

    Working with the Dynamic Type in C# https://www.red-gate.com/simple-talk/dotnet/c-programming/workin ...

  8. Dynamic Type

    啥是 Dynamic Type 动态字体,即视力不好的用户,调整了默认字体的大小,开发者应该根据这个设置,动态改变界面的字体等,保证用户能看得清楚. 这个还是蛮重要的,视力不好的人越来越多. 用户在哪 ...

  9. Deploying JRE (Native Plug-in) for Windows Clients in Oracle E-Business Suite Release 12 (文档 ID 393931.1)

    In This Document Section 1: Overview Section 2: Pre-Upgrade Steps Section 3: Upgrade and Configurati ...

随机推荐

  1. 标准程序员系列-Github篇-初始化一个代码仓库

    下面将一步步介绍怎样使用GitHub来初始化一个项目的版本控制仓库: 1. 到GitHub上注册自己的账号:https://github.com/ 2. 创建第一个代码仓库一个仓库相当于一个项目的代码 ...

  2. 关于vs2013error C4996: 'strcmpi': The POSIX name for this item is deprecated.的错误解决办法!

    1.出现如下错误(如图1) 2.解决办法(如图2)在头文件处添加#pragma warning(disable: 4996)

  3. 有时summary的状态和details是否有open属性有关

    用过mac的同学对这个界面一定很熟悉,因为这个界面和我们今天要说的details有很多相近的地方,首先,其有折叠效果,用户可以自己选择打开或关闭哪一个,其次,当我们直接打开的时候,默认会有几个标签是打 ...

  4. 布局共享(列如所有activity拥有相同的布局部分,比如actionbar,在BaseActivity中写入布局)

    有时候界面上会用到统一的布局,比如toolbar,你可能会想到在用到的地方都去加上toobar这样对于程序的开发与维护来说都显得特别麻烦,我们可以将他写在父类中. 首先创建一个BaseActivity ...

  5. mark 的总结开发笔记-备

    2.播放音乐:-(void) playMusic{@try{//取文件路径NSString *musicFilePath = [[NSBundle mainBundle] pathForResourc ...

  6. 关于DDMS查看Data文件夹

    真机是无法查看的,只有通过模拟器查看

  7. hdu 相遇周期

    #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int ...

  8. Unity 3D中的界面快捷键

    Ctrl+1 切换到Scene视图Ctrl+2 切换到Game视图Ctrl+3 切换到Inspector视图Ctrl+4 切换到Hierarchy视图Ctrl+5 切换到Project视图Ctrl+6 ...

  9. ThrottleStop

    ThrottleStop 我的要开这个软件,睿频才能开.不然一直工作在1.8Ghz下默认频率太低了开了这个速度才有提升

  10. 实现ECMAScript的引擎

    list of ECMAScript engines From Wikipedia, the free encyclopedia     An ECMAScript engine is a progr ...