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. 用lambda表达式替代 for循环进行批量操作。

    IEnumerable<Rect> rectlist3 = rectlist.Select(rect =>newRect(rect.X + 2000, rect.Y, rect.re ...

  2. commons-pool2-中的一些配置

      /**                     * 连接失效检测相关                     */                    // 空闲时进行连接测试,会启动异步evi ...

  3. 封装JDBC事务操作,执行存储过程测试

    Oracle数据库端测试环境见:http://www.cnblogs.com/yshyee/p/4392328.html package com.mw.utils; import java.sql.C ...

  4. Adt 配置注释模板

    点击Window->Preferences->Java->Code Style->Code Templates,如下图所示: 选中,点击右侧的Edit进行编辑.

  5. Content-Disposition的使用方法

    一.作用: 1)希望某类或者某已知MIME类型的文件(比如:*.gif;*txt;*.htm)能够在访问时弹出"文件下载对话框" 2)希望客户端下载时以指定文件名显示 3)希望某文 ...

  6. struct2(六) 为表单添加验证

    简介 为表单添加验证 添加校验的方法: 1. first name 不能为null 2. Email address 不能为null 3. age 必须大于18岁 为了在用户提交的时候,能够校验这个表 ...

  7. Corrupted MAC on input

    Corrupted MAC on input Incorrect MAC received on packet

  8. sqlite3 C接口

  9. windows 杀进程

    selenium自动化时,会启动chromedriver.exe,每次运行一次,就多启动一个,执行多次就会拖慢系统.如下批处理命令,可以批量杀掉进程 tasklist |find "chro ...

  10. (转)iOS Wow体验 - 第一章 - iOS人机界面设计规范纵览

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第一章译文精选,其余章节将陆续放出. 关于本套译文 ...