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. ubuntu 14.04解决gedit中文乱码的问题

    终端输入 gsettings set org.gnome.gedit.preferences.encodings auto-detected "['UTF-8','GB18030','GB2 ...

  2. 我和小美的撸码日记(2)之第一个基于MVC+Jqgrid的列表页面

    一.前言 “尼玛哥,上周你教我改了下OA系统UI,黄总看了很满意呀.”    “不错不错,看来小美进步很大,可以提前结束试用期,到时候加工资别忘了请我吃饭呀!”    “尼玛哥,你有女朋友了吗?” “ ...

  3. 钢管下料问题(钢管用量最少)Lingo求解

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang !钢管下料问题1(钢管用量最少) 题目: 钢管原料   每根19m 客户需求   4m   50根 ...

  4. AFNetworking 2.0 新特性讲解之AFHTTPSessionManager

    AFNetworking 2.0 新特性讲解之AFHTTPSessionManager (2014-02-17 11:56:24) 转载▼     AFNetworking 2.0 相比1.0 API ...

  5. DOM commend

    var comment = document.createComment("commend content"); var elem = document.getElementByI ...

  6. Java Thread Status(转)

    public static enum Thread.State  extends Enum<Thread.State>线程状态.线程可以处于下列状态之一: 1.NEW 至今尚未启动的线程的 ...

  7. BZOJ2212: [Poi2011]Tree Rotations

    2212: [Poi2011]Tree Rotations Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 391  Solved: 127[Submi ...

  8. editplus配置详:

    1:设置删除整行快捷键 2:设置背景颜色 3:php 开发环境 在 http://download.csdn.net/detail/vspeter/6002287 下载 editplus 的php语法 ...

  9. poj 3273 Monthly Expense(二分搜索之最大化最小值)

    Description Farmer John ≤ moneyi ≤ ,) that he will need to spend each day over the next N ( ≤ N ≤ ,) ...

  10. hdu 5072 Coprime (容斥)

    Problem Description There are n people standing in a line. Each of them has a unique id number. Now ...