zoukankan      html  css  js  c++  java
  • Azure Table storage 之改进DynamicTableEntity类为其添加动态语言扩展

    在之前的一篇文章中提到,storage类库中包含一个可以用来动态获取Azure table storage 表结构的类-DynamicTableEntity。

    我们可以通过这个类,我们无需为每一个表提前声明一个class,也能够对其进行操作。

    但在我们要添加Entity到表中的时候会感觉到一点不舒服

    以下我所希望使用的该类的方式:

    dynamic entity = new DynamicTableEntity();
    entity.Name=”sam”;
    entity.Gender=true;
    …
    

    这样的形式

    而实际代码却是

    DynamicTableEntity entity1 = new DynamicTableEntity();
                Dictionary<string, EntityProperty> data1 = new Dictionary<string, EntityProperty>();
                data1.Add("Name", new EntityProperty("Sam"));
                data1.Add("Gender", new EntityProperty(true));
                data1.Add("Age", new EntityProperty(18));
                entity1.Properties = data1;
                entity1.PartitionKey = "Partition1";
                entity1.RowKey = "1";
                UserDataList.Add(entity1);
    

      

    身为一个以dynamic开头的类居然不能够用dynamic关键字来初始化它,在实例化一个DynamicTableEntity类的时候居然要如此麻烦,实在让人不爽。

    所以, 经过一番研究,发现了一个可以支持动态扩展的类,为了与DynamicTableEntity区分开来,所以取名DynamicObjectTableEntity。它实现了DynamicTableEntity相同的功能,而且继承了DynamicObject,从而具有动态语言的特性,更加方便 使用。

    而且动态语言扩展一直以来除了在linq中使用比较多以外,其它地方基本看不到。这里正好通过对dynamicTableEntity的改造可以加深对动态语言扩展的理解。

    实现代码如下:

    public class DynamicObjectTableEntity : DynamicObject,ITableEntity
        {
            #region DynamicTableEntity's code
            // Methods
            public DynamicObjectTableEntity()
            {
                this.Properties = new Dictionary<string, EntityProperty>();
            }
    
            public DynamicObjectTableEntity(string partitionKey, string rowKey) : this(partitionKey, rowKey, DateTimeOffset.MinValue, null, new Dictionary<string, EntityProperty>())
            {
            }
    
            public DynamicObjectTableEntity(string partitionKey, string rowKey, string etag, IDictionary<string, EntityProperty> properties) : this(partitionKey, rowKey, DateTimeOffset.MinValue, etag, properties)
            {
            }
    
            internal DynamicObjectTableEntity(string partitionKey, string rowKey, DateTimeOffset timestamp, string etag, IDictionary<string, EntityProperty> properties)
            {
                //CommonUtility.AssertNotNull("partitionKey", partitionKey);
                //CommonUtility.AssertNotNull("rowKey", rowKey);
                //CommonUtility.AssertNotNull("properties", properties);
                this.PartitionKey = partitionKey;
                this.RowKey = rowKey;
                this.Timestamp = timestamp;
                this.ETag = etag;
                this.Properties = properties;
            }
    
            public void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
            {
                this.Properties = properties;
            }
    
            public IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
            {
                return this.Properties;
            }
    
            // Properties
            public string ETag { get; set; }
    
            public EntityProperty this[string key]
            {
                get
                {
                    return this.Properties[key];
                }
                set
                {
                    this.Properties[key] = value;
                }
            }
    
            public string PartitionKey { get; set; }
    
            public IDictionary<string, EntityProperty> Properties { get; set; }
    
            public string RowKey { get; set; }
    
            public DateTimeOffset Timestamp { get; set; }
    
            #endregion
    
            #region override DynamicObject's mehtods
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                if (!Properties.ContainsKey(binder.Name))
                    Properties.Add(binder.Name, ConvertToEntityProperty(binder.Name, null));
                result = Properties[binder.Name];
                return true;
            }
    
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                EntityProperty property = ConvertToEntityProperty(binder.Name, value);
    
                if (Properties.ContainsKey(binder.Name))
                    Properties[binder.Name] = property;
                else
                    Properties.Add(binder.Name, property);
    
                return true;
            }
    
            /// <summary>
            /// Convert object value to EntityProperty.
            /// </summary>
            private EntityProperty ConvertToEntityProperty(string key, object value)
            {
                if (value == null) return new EntityProperty((string)null);
                if (value.GetType() == typeof(byte[]))
                    return new EntityProperty((byte[])value);
                if (value.GetType() == typeof(bool))
                    return new EntityProperty((bool)value);
                if (value.GetType() == typeof(DateTimeOffset))
                    return new EntityProperty((DateTimeOffset)value);
                if (value.GetType() == typeof(DateTime))
                    return new EntityProperty((DateTime)value);
                if (value.GetType() == typeof(double))
                    return new EntityProperty((double)value);
                if (value.GetType() == typeof(Guid))
                    return new EntityProperty((Guid)value);
                if (value.GetType() == typeof(int))
                    return new EntityProperty((int)value);
                if (value.GetType() == typeof(long))
                    return new EntityProperty((long)value);
                if (value.GetType() == typeof(string))
                    return new EntityProperty((string)value);
                throw new Exception("This value type" + value.GetType() + " for " + key);
                throw new Exception(string.Format("This value type {0} is not supported for {1}", key));
            }
    
            /// <summary>
            /// Get the edm type, if the type is not a edm type throw a exception.
            /// </summary>
            private Type GetType(EdmType edmType)
            {
                switch (edmType)
                {
                    case EdmType.Binary:
                        return typeof(byte[]);
                    case EdmType.Boolean:
                        return typeof(bool);
                    case EdmType.DateTime:
                        return typeof(DateTime);
                    case EdmType.Double:
                        return typeof(double);
                    case EdmType.Guid:
                        return typeof(Guid);
                    case EdmType.Int32:
                        return typeof(int);
                    case EdmType.Int64:
                        return typeof(long);
                    case EdmType.String:
                        return typeof(string);
                    default: throw new TypeLoadException(string.Format("not supported edmType:{0}", edmType));
                }
            }
    
            #endregion
        }
    

     

    在使用了如下类之后,我们就可以用我预期的代码来操作table 了

    代码如下:

    static void Main(string[] args)
            {
                var connectionString = "DefaultEndpointsProtocol=https;AccountName=[Account];AccountKey=[Key]";
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
                try
                {
                    var client = storageAccount.CreateCloudTableClient();
                    var table = client.GetTableReference("ShortMessages");
                    table.CreateIfNotExists();
                    dynamic entity = new DynamicObjectTableEntity("default", DateTime.Now.ToShortTimeString());
    
                    entity.Name = "pete";
                    entity.Message = "Hello";
                    table.Execute(TableOperation.Insert(entity));
                    Console.WriteLine("insert successfully!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.Read();    
            }
    

      

    示例参考MSDN:http://code.msdn.microsoft.com/Dynamic-TableServiceEntity-151d661f

     

     

  • 相关阅读:
    实用机器学习 跟李沐学AI
    Explicitly drop temp table or let SQL Server handle it
    dotnettransformxdt and FatAntelope
    QQ拼音输入法 禁用模糊音
    (技术八卦)Java VS RoR
    Ruby on rails开发从头来(windows)(七)创建在线购物页面
    Ruby on rails开发从头来(windows)(十三)订单(Order)
    Ruby on rails开发从头来(windows)(十一)订单(Order)
    新员工自缢身亡,华为又站到了风口浪尖
    死亡汽油弹(Napalm Death)乐队的视频和来中国演出的消息
  • 原文地址:https://www.cnblogs.com/he-yuan/p/3386143.html
Copyright © 2011-2022 走看看